1. Introduction and Aims

We have quality-controlled the 10X data and the SS2 data and now are left with the following objects:

10X 5K data - pb_sex_filtered

10X 30K data - pb_30k_sex_filtered

SS2 mutant data - ss2_mutants_final

2. Read in the data

Load/Install the Required Packages

[1] "patchwork is loaded correctly"
[1] "viridis is loaded correctly"
[1] "Seurat is loaded correctly"
Loading required package: cowplot

Attaching package: ‘cowplot’

The following object is masked from ‘package:patchwork’:

    align_plots
[1] "cowplot is loaded correctly"
Loading required package: gridExtra
[1] "gridExtra is loaded correctly"
Loading required package: grid
[1] "grid is loaded correctly"
Loading required package: Hmisc
Loading required package: lattice
Loading required package: survival
Loading required package: Formula
Loading required package: ggplot2

Attaching package: ‘Hmisc’

The following object is masked from ‘package:Seurat’:

    Key

The following objects are masked from ‘package:base’:

    format.pval, units
[1] "Hmisc is loaded correctly"
Loading required package: reshape2
[1] "reshape2 is loaded correctly"
Loading required package: dplyr

Attaching package: ‘dplyr’

The following objects are masked from ‘package:Hmisc’:

    src, summarize

The following object is masked from ‘package:gridExtra’:

    combine

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
[1] "dplyr is loaded correctly"
Loading required package: Nebulosa
[1] "Nebulosa is loaded correctly"
Loading required package: monocle3
Loading required package: Biobase
Loading required package: BiocGenerics
Loading required package: parallel

Attaching package: ‘BiocGenerics’

The following objects are masked from ‘package:parallel’:

    clusterApply, clusterApplyLB, clusterCall, clusterEvalQ, clusterExport, clusterMap, parApply, parCapply,
    parLapply, parLapplyLB, parRapply, parSapply, parSapplyLB

The following objects are masked from ‘package:dplyr’:

    combine, intersect, setdiff, union

The following object is masked from ‘package:gridExtra’:

    combine

The following objects are masked from ‘package:stats’:

    IQR, mad, sd, var, xtabs

The following objects are masked from ‘package:base’:

    anyDuplicated, append, as.data.frame, basename, cbind, colnames, dirname, do.call, duplicated, eval, evalq,
    Filter, Find, get, grep, grepl, intersect, is.unsorted, lapply, Map, mapply, match, mget, order, paste, pmax,
    pmax.int, pmin, pmin.int, Position, rank, rbind, Reduce, rownames, sapply, setdiff, sort, table, tapply,
    union, unique, unsplit, which, which.max, which.min

Welcome to Bioconductor

    Vignettes contain introductory material; view with 'browseVignettes()'. To cite Bioconductor, see
    'citation("Biobase")', and for packages 'citation("pkgname")'.


Attaching package: ‘Biobase’

The following object is masked from ‘package:Hmisc’:

    contents

Loading required package: SingleCellExperiment
Loading required package: SummarizedExperiment
Loading required package: GenomicRanges
Loading required package: stats4
Loading required package: S4Vectors

Attaching package: ‘S4Vectors’

The following objects are masked from ‘package:dplyr’:

    first, rename

The following object is masked from ‘package:base’:

    expand.grid

Loading required package: IRanges

Attaching package: ‘IRanges’

The following objects are masked from ‘package:dplyr’:

    collapse, desc, slice

Loading required package: GenomeInfoDb
Loading required package: DelayedArray
Loading required package: matrixStats

Attaching package: ‘matrixStats’

The following objects are masked from ‘package:Biobase’:

    anyMissing, rowMedians

The following object is masked from ‘package:dplyr’:

    count


Attaching package: ‘DelayedArray’

The following objects are masked from ‘package:matrixStats’:

    colMaxs, colMins, colRanges, rowMaxs, rowMins, rowRanges

The following objects are masked from ‘package:base’:

    aperm, apply, rowsum


Attaching package: ‘SummarizedExperiment’

The following object is masked from ‘package:Seurat’:

    Assays


Attaching package: ‘monocle3’

The following objects are masked from ‘package:Biobase’:

    exprs, fData, fData<-, pData, pData<-
[1] "monocle3 is loaded correctly"

Read in the Data

screen hits

## EDIT - change this to the excel table once we have it finalized for the screen
screen_hits <- c("PBANKA-0516300",
"PBANKA-1217700",
"PBANKA-0409100",
"PBANKA-1034300",
"PBANKA-1437500",
"PBANKA-0827500",
"PBANKA-0824300",
"PBANKA-1426900",
"PBANKA-0105300",
"PBANKA-0921100",
"PBANKA-1002400",
"PBANKA-0829400",
"PBANKA-1347200",
"PBANKA-0828000",
"PBANKA-0902300",
"PBANKA-1418100",
"PBANKA-1435200",
"PBANKA-1454800",
"PBANKA-0712300",
"PBANKA-0410500",
"PBANKA-1144800",
"PBANKA-1231600",
"PBANKA-0503200",
"PBANKA-0308900",
"PBANKA-1214700",
"PBANKA-0709900",
"PBANKA-0311900",
"PBANKA-0716500",
"PBANKA-1447900",
"PBANKA-0102200",
"PBANKA-0713500",
"PBANKA-0102400",
"PBANKA-1302700",
"PBANKA-1235900",
"PBANKA-0401100",
"PBANKA-0413400",
"PBANKA-1126900",
"PBANKA-1425900",
"PBANKA-0418300",
"PBANKA-1464600",
"PBANKA-0806000")

Read in gene annotations

gene_annotations <- read.table("../data/Reference/GenesByTaxon_Summary.csv", header = TRUE, sep = ",", stringsAsFactors = TRUE)
dim(gene_annotations)

## convert _ to -
gene_annotations$Gene.ID <- gsub("_", "-", gene_annotations$Gene.ID)

load in datasets

paste("10x dataset")
[1] "10x dataset"
pb_sex_filtered
An object of class Seurat 
5098 features across 6191 samples within 1 assay 
Active assay: RNA (5098 features, 2000 variable features)
 2 dimensional reductions calculated: pca, umap
paste("Smart-seq2 dataset")
[1] "Smart-seq2 dataset"
ss2_mutants_final
An object of class Seurat 
5245 features across 2717 samples within 1 assay 
Active assay: RNA (5245 features, 2000 variable features)
 2 dimensional reductions calculated: pca, umap
paste("The composition of the Smart-seq2 dataset is:")
[1] "The composition of the Smart-seq2 dataset is:"
table(ss2_mutants_final@meta.data$genotype)

Mutant     WT 
  2028    689 

3. Merging the Smart-seq2 and 10X Data

Prepare data

tenx_5k_counts_to_integrate
An object of class Seurat 
5098 features across 6191 samples within 1 assay 
Active assay: RNA (5098 features, 0 variable features)

We need to make sure the mutant data is compatible with the 10X data. the 10X data has fewer genes represented so we need to find the intersect of the two before integration.

GCSKO_mutants
An object of class Seurat 
5018 features across 2717 samples within 1 assay 
Active assay: RNA (5018 features, 0 variable features)
## double check that this is the same number of genes
## subset counts so that only genes represented in the other two objects are there:
length(intersect(rownames(tenx_5k_counts), rownames(mutant_counts_for_integration)))
[1] 5018

IMPORTANT - this next step is different to GCSKO_merge as it subsets the smart-seq2 data into wild-type only.

## subset wt on ss2 data:
ss2_wt_cells <- rownames(GCSKO_mutants@meta.data[GCSKO_mutants@meta.data$genotype == "WT", ])
GCSKO_mutants_wtonly <- subset(GCSKO_mutants, cells = ss2_wt_cells)

create list and normalise:

## make list
tenx.justwt.list <- list(tenx_5k_counts_to_integrate, GCSKO_mutants_wtonly)

## prepare data
for (i in 1:length(tenx.justwt.list)) {
    tenx.justwt.list[[i]] <- NormalizeData(tenx.justwt.list[[i]], verbose = FALSE)
    tenx.justwt.list[[i]] <- FindVariableFeatures(tenx.justwt.list[[i]], selection.method = "vst", 
        nfeatures = 2000, verbose = FALSE)
    all.genes <- rownames(tenx.justwt.list[[i]])
    tenx.justwt.list[[i]] <- ScaleData(tenx.justwt.list[[i]], features = all.genes)
}

Integrate objects

## Find anchors
tenx.justwt.anchors <- FindIntegrationAnchors(object.list = tenx.justwt.list, dims = 1:21, verbose = FALSE)

## Integrate data
tenx.justwt.integrated <- IntegrateData(anchorset = tenx.justwt.anchors, dims = 1:21, verbose = FALSE, features.to.integrate = genes_in_tenx_dataset)

4. Dimensionality reduction

PCA

Optimised UMAP

After optimisation, the following UMAP can be calculated:

## Run optimised UMAP
tenx.justwt.integrated <- RunUMAP(tenx.justwt.integrated, reduction = "pca", dims = 1:10, n.neighbors = 50, seed.use = 1234, min.dist = 0.4, repulsion.strength = 0.03, local.connectivity = 150)

Make final plots:


## split seurat object up
ob.list <- SplitObject(tenx.justwt.integrated, split.by = "experiment")

## make plots for each object
plot.list <- lapply(X = ob.list, FUN = function(x) {
    DimPlot(x, dims = c(1,2), pt.size = 1) + theme(legend.position="bottom")
})

composition_umap_10x <- plot.list$`tenx_5k` + 
  coord_fixed() +
  theme_void() +
  scale_color_manual(values=c(replicate(45, "#999999"))) +
  labs(title = paste("10x (wild-type)")) +
  theme(legend.position = "none", plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold"))

composition_umap_ss2 <- plot.list$mutants +
  coord_fixed() +
  theme_void() +
  scale_color_manual(values=c(replicate(46, "#999999"))) +
  labs(title = paste("Smart-seq2 (wild-type)")) +
  theme(legend.position = "none", plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold"))

composition_umap <- composition_umap_10x + composition_umap_ss2 

composition_umap

save

ggsave("../images_to_export/composition_umap.png", plot = composition_umap, device = "png", path = NULL, scale = 1, width = 20, height = 20, units = "cm", dpi = 300, limitsize = TRUE)
## make plots
## hoo dataset correlation
UMAP_hoo <- DimPlot(tenx.justwt.integrated, pt.size = 0.1, group.by = "Prediction.Spearman.", dims = c(1,2)) +
  coord_fixed() + 
  theme_void() +
  labs(title = paste("Hoo Predicted Timepoint")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) +
  scale_colour_manual(values = inferno(12))  +
  labs(colour = "hour") +
  theme(legend.position = "bottom", legend.title=element_text(size=10))

## ap2g timecourse in this paper correlation
UMAP_kasia <- DimPlot(tenx.justwt.integrated, pt.size = 0.1, group.by = "Prediction.Spearman._Kasia", dims = c(1,2)) +
  coord_fixed() + 
  theme_void() +
  labs(title = paste("AP2G Timecourse Predicted Timepoint")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) +
  scale_colour_manual(values = inferno(10))  +
  labs(colour = "hour") +
  theme(legend.position = "bottom", legend.title=element_text(size=10))

## combine
umap_bulk <- wrap_plots(UMAP_hoo, UMAP_kasia, ncol = 2)

## print
umap_bulk

5. Clustering

Generate clusters

## generate new clusters at low resolution
tenx.justwt.integrated <- FindNeighbors(tenx.justwt.integrated, dims = 1:19, reduction = "pca")
tenx.justwt.integrated <- FindClusters(tenx.justwt.integrated, resolution = 2, random.seed = 42, algorithm = 2)

visualise clusters

DimPlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE, repel = FALSE, label = TRUE)

Make individual plots highlighting where cells in each cluster fall

[1] 24

plot

## this function writes the next bit of code for you
## put it into the console and paste the response
#ploty <- c()
#for(i in seq_along(levels(tenx.justwt.integrated@meta.data$seurat_clusters))){
#  ploty <- paste0(ploty, "list_UMAPs_by_cluster[[", i, "]]", " + ")
#}

## plot
list_UMAPs_by_cluster[[1]] + list_UMAPs_by_cluster[[2]] + list_UMAPs_by_cluster[[3]] + list_UMAPs_by_cluster[[4]] + list_UMAPs_by_cluster[[5]] + list_UMAPs_by_cluster[[6]] + list_UMAPs_by_cluster[[7]] + list_UMAPs_by_cluster[[8]] + list_UMAPs_by_cluster[[9]] + list_UMAPs_by_cluster[[10]] + list_UMAPs_by_cluster[[11]] + list_UMAPs_by_cluster[[12]] + list_UMAPs_by_cluster[[13]] + list_UMAPs_by_cluster[[14]] + list_UMAPs_by_cluster[[15]] + list_UMAPs_by_cluster[[16]] + list_UMAPs_by_cluster[[17]] + list_UMAPs_by_cluster[[18]] + list_UMAPs_by_cluster[[19]] + list_UMAPs_by_cluster[[20]] + list_UMAPs_by_cluster[[21]] + list_UMAPs_by_cluster[[22]] + list_UMAPs_by_cluster[[23]] + list_UMAPs_by_cluster[[24]]

Find Markers

visualise markers

## get the top 10 for each cluster
top10 <- pb.markers %>% group_by(cluster) %>% top_n(n = 10, wt = avg_logFC)

## scale data is missing - but original dfs have scale.data
# df_scaled <- as.matrix(transform(merge(as.data.frame(tenx.justwt.list[[1]]@assays$RNA@scale.data), as.data.frame(tenx.justwt.list[[2]]@assays$RNA@scale.data), by = 0, all=FALSE), row.names=Row.names, Row.names=NULL))
# tenx.justwt.integrated@assays$RNA@scale.data <- df_scaled

## scale data in RNA slot
all.genes <- rownames(tenx.justwt.integrated)
tenx.justwt.integrated <- ScaleData(tenx.justwt.integrated, vars.to.regress = 'experiment', features = all.genes)

## heatmap
DoHeatmap(tenx.justwt.integrated, features = top10$gene) + NoLegend()

6. Define Cluster Identities

Downsampling

# ## check number of cells in each cluster
# df_clusters <- as.data.frame(table(tenx.justwt.integrated@meta.data$integrated_snn_res.2))
# plot(df_clusters)
# 
# ## downsample using appropriate metrics
# tenx.justwt.integrated.downsampled <- subset(tenx.justwt.integrated, downsample = 100)
#   
# ## inspect plot
# FeaturePlot(tenx.justwt.integrated.downsampled, features = "PBANKA-1437500", coord.fixed = TRUE, dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
#   theme_void() + 
#   labs(title = paste("AP2G (Commitment)")) + 
#   theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
#   scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

Marker Genes

useful tools for all plots

## define male and female symbol
female_symbol <- intToUtf8(9792)
male_symbol <- intToUtf8(9794)

## define colour pal
marker_gene_ramp <- colorRampPalette(c("#D3D3D3", "#1D1564"))(50)

Expression - cutoffs - purple


marker_gene_plot_CCP2 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-1319500", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE, 
                                     slot = 'scale.data') + 
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(ccp2)~(Female))) + 
                          theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=6.0), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MG1 <- FeaturePlot(tenx.justwt.integrated, 
                                    features = "PBANKA-0416100", 
                                    coord.fixed = TRUE, 
                                    min.cutoff = "q05", 
                                    max.cutoff = "q95", 
                                    dims = c(1,2), 
                                    reduction = "umap", 
                                    pt.size = 0.5, 
                                    order = TRUE, 
                                    slot = 'scale.data') +
                        coord_fixed() + 
                        theme_void() + 
                        labs(title = expression(italic(mg1)~(Male))) + 
                        theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                        scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_AP2G <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-1437500", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE, 
                                     slot = 'scale.data') + 
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(ap2g)~(Commitment))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MSP1 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-0831000", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE, 
                                     slot = 'scale.data') + 
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(msp1)~(Schizont))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MSP8 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-1102200", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE, 
                                     slot = 'scale.data') + 
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(msp8)~(Asexual))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-1102200 in the default search locations, found in RNA assay insteadCoordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_SBP1 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-1101300", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE,
                                     slot = 'scale.data') +
                          coord_fixed() + 
                          theme_void() + 
                          labs(title = expression(italic(SBP1)~(Ring))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_FAMB <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-0722600", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE,
                                     slot = 'scale.data') +
                          coord_fixed() + 
                          theme_void() + 
                          labs(title = expression(italic(fam-b2)~(Ring))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-0722600 in the default search locations, found in RNA assay insteadCoordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_ORC1 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-0602000", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE,
                                     slot = 'scale.data') +
                          coord_fixed() + 
                          theme_void() + 
                          labs(title = expression(italic(orc1)~(DNA~replication))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-0602000 in the default search locations, found in RNA assay insteadCoordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_CDPK5 <- FeaturePlot(tenx.justwt.integrated, 
                                      features = "PBANKA-1351500", 
                                      coord.fixed = TRUE, 
                                      min.cutoff = "q05", 
                                      max.cutoff = "q95", 
                                      dims = c(1,2), 
                                      reduction = "umap", 
                                      pt.size = 0.5, 
                                      order = TRUE, 
                                      slot = 'scale.data') +
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(cdpk5)~(Line~Schizont))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MCM4 <- FeaturePlot(tenx.justwt.integrated, 
                                      features = "PBANKA-1415600", 
                                      coord.fixed = TRUE, 
                                      min.cutoff = "q05", 
                                      max.cutoff = "q95", 
                                      dims = c(1,2), 
                                      reduction = "umap", 
                                      pt.size = 0.5, 
                                      order = TRUE, 
                                      slot = 'scale.data') +
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(mcm4)~(DNA~replication))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
# + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

## plot
## cowplot method
marker_gene_plot_all <- plot_grid(marker_gene_plot_FAMB, marker_gene_plot_MSP8, marker_gene_plot_MSP1, marker_gene_plot_AP2G, marker_gene_plot_CCP2, marker_gene_plot_MG1, marker_gene_plot_HSP70, nrow=3)

marker_gene_plot_all

Mutant Genes

Expression - with cutoffs

# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-0102400         GCSKO-2  MD4 
# PBANKA-0716500        GCSKO-19  MD5 
# PBANKA-1435200        GCSKO-20  FD4 
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-0413400    GCSKO-10_820  MD3
# PBANKA-0828000         GCSKO-3  GD1
# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-1144800        GCSKO-28  FD5


marker_gene_plot_fd3 <- FeaturePlot(tenx.justwt.integrated, 
                                   dims = c(1,2), 
                                   reduction = "umap", 
                                   features = "PBANKA-1418100", 
                                   coord.fixed = TRUE,
                                   min.cutoff = "q05", 
                                   max.cutoff = "q95", 
                                   pt.size = 0.5, 
                                   order = TRUE, 
                                   slot = 'scale.data') + 
                        theme_void() + 
                        labs(title = expression(italic(fd3))) + 
                        theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-1418100 in the default search locations, found in RNA assay insteadScale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                        ## add sex symbols
                        #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                        #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_md4 <- FeaturePlot(tenx.justwt.integrated, 
                                  dims = c(1,2), 
                                  reduction = "umap", 
                                  features = "PBANKA-0102400", 
                                  coord.fixed = TRUE, 
                                  min.cutoff = "q05",
                                  max.cutoff = "q95", 
                                  pt.size = 0.5, 
                                  order = TRUE, 
                                  slot = 'scale.data') + 
                      theme_void() + 
                      labs(title = expression(italic(md4))) + 
                      theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                      ## add sex symbols
                      #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                      #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_md5 <- FeaturePlot(tenx.justwt.integrated, 
                                   dims = c(1,2), 
                                   reduction = "umap", 
                                   features = "PBANKA-0716500", 
                                   coord.fixed = TRUE, 
                                   min.cutoff = "q05", 
                                   max.cutoff = "q95",
                                   pt.size = 0.5, 
                                   order = TRUE, 
                                   slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(md5))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = "")) 
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_fd4 <- FeaturePlot(tenx.justwt.integrated, 
                                   dims = c(1,2), 
                                   reduction = "umap", 
                                   features = "PBANKA-1435200", 
                                   coord.fixed = TRUE, 
                                   min.cutoff = "q05", 
                                   max.cutoff = "q95", 
                                   pt.size = 0.5, 
                                   order = TRUE, 
                                   slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(fd4))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = "")) 
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_fd2 <- FeaturePlot(tenx.justwt.integrated, 
                                    dims = c(1,2), 
                                    reduction = "umap", 
                                    features = "PBANKA-0902300", 
                                    coord.fixed = TRUE, 
                                    min.cutoff = "q05", 
                                    max.cutoff = "q95", 
                                    pt.size = 0.5, 
                                    order = TRUE, 
                                    slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(fd2))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       # + annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_md3 <- FeaturePlot(tenx.justwt.integrated, 
                                   dims = c(1,2), 
                                   reduction = "umap", 
                                   features = "PBANKA-0413400", 
                                   coord.fixed = TRUE, 
                                   min.cutoff = "q05", 
                                   max.cutoff = "q95",
                                   pt.size = 0.5, 
                                   order = TRUE, 
                                   slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(md3))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-0413400 in the default search locations, found in RNA assay insteadScale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                      #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_gd1 <- FeaturePlot(tenx.justwt.integrated, 
                                  dims = c(1,2), 
                                  reduction = "umap",
                                  features = "PBANKA-0828000", 
                                  coord.fixed = TRUE, 
                                  min.cutoff = "q05", 
                                  max.cutoff = "q95",
                                  pt.size = 0.5, 
                                  order = TRUE, 
                                  slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(gd1))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-0828000 in the default search locations, found in RNA assay insteadScale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_md1 <- FeaturePlot(tenx.justwt.integrated, 
                                    dims = c(1,2), 
                                    reduction = "umap", 
                                    features = "PBANKA-1302700",
                                    coord.fixed = TRUE,
                                    min.cutoff = "q05", 
                                    max.cutoff = "q95", 
                                    pt.size = 0.5, 
                                    order = TRUE, 
                                    slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(md1))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_md2 <- FeaturePlot(tenx.justwt.integrated,
                                   dims = c(1,2), 
                                   reduction = "umap",
                                   features = "PBANKA-1447900",
                                   coord.fixed = TRUE,
                                   min.cutoff = "q05", 
                                   max.cutoff = "q95", 
                                   pt.size = 0.5, 
                                   order = TRUE, 
                                   slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(md2))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_fd1 <- FeaturePlot(tenx.justwt.integrated, 
                                    dims = c(1,2), 
                                    reduction = "umap", 
                                    features = "PBANKA-1454800", 
                                    coord.fixed = TRUE, 
                                    min.cutoff = "q05",
                                    max.cutoff = "q95", 
                                    pt.size = 0.5, 
                                    order = TRUE, 
                                    slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(fd1))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

##original label:
# labs(title = paste("(CCP2; Female)","\n", "PBANKA_1319500"))
# scale_color_continuous_sequential(palette = "Purples 2")
# scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

## make composite plot
mutant_expression_composite <- wrap_plots(marker_gene_plot_gd1 , marker_gene_plot_md1 , marker_gene_plot_md2 , marker_gene_plot_md3 , marker_gene_plot_md4 , marker_gene_plot_md5 , marker_gene_plot_fd1 , marker_gene_plot_fd2 , marker_gene_plot_fd3 , marker_gene_plot_fd4, ncol = 4)
           
## print
mutant_expression_composite

save

ggsave("../images_to_export/ALL_CELLS_wt_gene_expression.png", plot = mutant_expression_composite, device = "png", path = NULL, scale = 1, width = 21, height = 29.7, units = "cm", dpi = 300, limitsize = TRUE)
# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-0102400         GCSKO-2  MD3 
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-1435200        GCSKO-20  FD4 
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-0413400    GCSKO-10_820  MD5
# PBANKA-0828000         GCSKO-3  GD1
# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-1144800        GCSKO-28  FD5


marker_gene_plot_17 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1418100", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd3")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_2 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0102400", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md3")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_19 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0716500", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md4")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_20 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1435200", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd4")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_13 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0902300", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd2")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_10 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0413400", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md5")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_3 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0828000", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("gd1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_oom <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1302700", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_29 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1447900", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md2")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_21 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1454800", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

##original label:
# labs(title = paste("(CCP2; Female)","\n", "PBANKA_1319500"))

## make composite plot
mutant_expression_composite <- wrap_plots(marker_gene_plot_17 , marker_gene_plot_2 , marker_gene_plot_19 , marker_gene_plot_20 , marker_gene_plot_13 , marker_gene_plot_10 , marker_gene_plot_3 , marker_gene_plot_oom , marker_gene_plot_29 , marker_gene_plot_21 , ncol = 4)
           
## print
mutant_expression_composite

7. Pseudotime on all cells

Pseudotime calculation

save

ggsave("../images_to_export/UMAP_pt_wt.png", plot = umap_pt, device = "png", path = NULL, scale = 1, width = 20, height = 20, units = "cm", dpi = 300, limitsize = TRUE)

gganimnate GIF of pseuodtime

#install.packages("gganimate")
library(gganimate)
#install.packages("gifski")
#install.packages("av")
#library(gifski)
#library(av)

## make dataframe for plotting
## extract data for GGplot version of this
df_animation <- as.data.frame(monocle.object.all@int_colData@listData$reducedDims@listData[["UMAP"]])
## add pt to this data frame:
pt_values <- as.data.frame(pseudotime(monocle.object.all, reduction_method = "UMAP"))
df_animation <- merge(df_animation, pt_values, by="row.names") 
rownames(df_animation) <- df_animation$Row.names
colnames(df_animation)[4] <- "pt"

## make the static plot
p <- ggplot(df_animation, aes(x = UMAP_1, y = UMAP_2, colour = pt)) +
  geom_point() +
  scale_colour_viridis_c(option = "plasma") +
  coord_fixed() +
  theme_void() +
  theme(legend.position = "none")
## view plot
plot(p)

## make animated plot
## make a category for animation
#df_animation$group <- cut(df_animation$pt, 15)

anim <- p +
  transition_time(pt) +
  shadow_mark()

animate(anim, height = 3, width = 3, units = "in", res = 150, bg = 'transparent')

## to change the resolution - https://stackoverflow.com/questions/49058567/define-size-for-gif-created-by-gganimate-change-dimension-resolution 

Save animation

anim_save("animated_UMAP_transparent_bg_wt.gif", path = "../images_to_export/")
## extract pt values
pt_values <- as.data.frame(pseudotime(monocle.object.all, reduction_method = "UMAP"))

tenx.justwt.integrated <- AddMetaData(tenx.justwt.integrated, pt_values, "old_pt_values")

Define cell identities with branches

Define identities of cells

male

monocle.object_male <- choose_graph_segments(monocle.object.all)

female

monocle.object_female <- choose_graph_segments(monocle.object.all)

bipotential

monocle.object_bipot <- choose_graph_segments(monocle.object.all)

asexual (pre-branch)

monocle.object_asex_pre <- choose_graph_segments(monocle.object.all)

asexual fate

monocle.object_asex_fate <- choose_graph_segments(monocle.object.all)

check

df_freq <- data.frame(table(c(colnames(monocle.object_male), colnames(monocle.object_female), colnames(monocle.object_bipot), colnames(monocle.object_asex_pre), colnames(monocle.object_asex_fate))))
paste("number of cells in seurat object is", length(colnames(monocle.object.all)), ". The number of cells selected here with an identitity is", dim(df_freq)[1])
df_freq <- df_freq[df_freq$Freq > 1, ]
df_freq

Inspect where these missing cells are:

# '%ni%' <- Negate('%in%')
# 
# not_assigned_cells <- colnames(monocle.object.all)[colnames(monocle.object.all) %ni% c(colnames(monocle.object_male), colnames(monocle.object_female), colnames(monocle.object_bipot), colnames(monocle.object_asex), colnames(monocle.object_asex_fate))]
# 
# DimPlot(seurat.object, repel = TRUE, label.size = 5, pt.size = 0.5, cells.highlight = not_assigned_cells, dims = c(2,1), reduction = "DIM_UMAP") +
#   coord_fixed() + 
#   scale_color_manual(values=c("#000000", "#f54e1e"))
## create annotation dataframe from these results:
df_monocle_sexes <- rbind(data.frame("cell_name" = colnames(monocle.object_male), "sex" = rep("Male", length(colnames(monocle.object_male)))),
                          data.frame("cell_name" = colnames(monocle.object_female), "sex" = rep("Female", length(colnames(monocle.object_female)))),
                          data.frame("cell_name" = colnames(monocle.object_bipot), "sex" = rep("Bipotential", length(colnames(monocle.object_bipot)))),
                          data.frame("cell_name" = colnames(monocle.object_asex_pre), "sex" = rep("Asexual_Early", length(colnames(monocle.object_asex_pre)))),
                          data.frame("cell_name" = colnames(monocle.object_asex_fate), "sex" = rep("Asexual_Late", length(colnames(monocle.object_asex_fate))))
                          #data.frame("cell_name" = not_assigned_cells, "sex" = rep("Unassigned", length(not_assigned_cells)))
                          )

dim(df_monocle_sexes)

## order like the metadata
df_monocle_sexes <- df_monocle_sexes[match(rownames(monocle.object.all@colData), df_monocle_sexes$cell_name), ]

## add this back into the monocle object
monocle.object.all@colData$Sexes_monocle <- df_monocle_sexes$sex

## add this to the seurat object
rownames(df_monocle_sexes) <- df_monocle_sexes$cell_name
df_monocle_sexes_to_add_to_seurat <- df_monocle_sexes[,c("sex"), drop = FALSE]
tenx.justwt.integrated <- AddMetaData(tenx.justwt.integrated, df_monocle_sexes_to_add_to_seurat, col.name = "monocle_sex")

pt vs. real time

gg <- ggplot(df_plotting, aes(as.factor(Prediction.Spearman.), fill = monocle_sex)) + geom_bar(stat = "count", position="fill")

gg

8. Plots

make composite pseudotime/ID figure

save

#ggsave("../images_to_export/umap_id_pt.png", plot = umap_id_pt, device = "png", path = NULL, scale = 1, width = 21, height = 29.7, units = "cm", dpi = 300, limitsize = TRUE)

cluster plot

## these get defined later on, but are replicated above here for plotting
asexual_early_clusters <- c(9, 4, 15, 8, 1, 14, 2, 10, 3, 0, 6, 5)
asexual_late_clusters <- c(7, 12, 18, 20, 23)
bipotentional_early_clusters <- # 0?
bipotential_clusters <- c(11) 
male_clusters <- c(16, 13)
female_clusters <- c(21, 22, 17, 19)

## make a new column for plotting
tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting <- tenx.justwt.integrated@meta.data$seurat_clusters

## reorder the levels so you can plot the cluters as you wish
my_levels <- c(asexual_early_clusters,asexual_late_clusters, bipotential_clusters, male_clusters, female_clusters)
tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting <- factor(x = tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting, levels = my_levels)

## change the levels
levels(tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting) <- list(A_1="9", 
                                      A_2="4", 
                                      A_3="15", 
                                      A_4 = "8", 
                                      A_5 = "1",
                                      A_6=  "14", 
                                      A_7 = "2", 
                                      A_8 = "10",
                                      A_9 = "3",
                                      A_10 = "0",
                                      A_11 = "6",
                                      A_12 = "5",
                                      A_13 = "7",
                                      A_14 = "12",
                                      A_15 = "18",
                                      A_16 = "20",
                                      A_17 = "23",
                                      P = "11",
                                      M_1 = "16",
                                      M_2 = "13",
                                      F_1 = "21",
                                      F_2 = "22",
                                      F_3 = "19",
                                      F_3 = "17"
                                      )

### Annotation set-up

## extract pseudotime numbers and identity of cells to a dataframe
df_pt_id <- tenx.justwt.integrated@meta.data[,c("old_pt_values", "monocle_sex", "seurat_clusters_dot_plotting", "Prediction.Spearman.", "Prediction.Spearman._Kasia")]

## make a new column
df_pt_id$colour <- NA

## assign bins to each of the values
## help here: https://stackoverflow.com/questions/9946630/colour-points-in-a-plot-differently-depending-on-a-vector-of-values 
df_pt_id[df_pt_id$monocle_sex == "Asexual_Early" | df_pt_id$monocle_sex == "Asexual_Late", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Asexual_Early" | df_pt_id$monocle_sex == "Asexual_Late", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Male", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Male", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Female", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Female", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Bipotential", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Bipotential", ]$old_pt_values,breaks = 100))

## make colour ramps
asex_ramp <- colorRampPalette(c("#D5E3F5", "#0052c5"))
male_ramp <- colorRampPalette(c("white", "yellow", "#016c00"))
female_ramp <- colorRampPalette(c("yellow", "#a52b1e"))
bipot_ramp <- colorRampPalette(c("white", "#ffe400"))

## assign values to each cluster
## take the mean of the bin
df_annotation <- aggregate(df_pt_id[, "colour"], list(df_pt_id$seurat_clusters_dot_plotting), mean)
## BECAUSE we have ordered the clusters already, we can simply take the row index for this bit
df_annotation$colour <- NA
df_annotation[1:17, ]$colour <- asex_ramp(100)[df_annotation[1:17, ]$x]
df_annotation[18, ]$colour <- bipot_ramp(100)[df_annotation[18, ]$x]
df_annotation[19:20, ]$colour <- male_ramp(100)[df_annotation[19:20, ]$x]
df_annotation[21:23, ]$colour <- female_ramp(100)[df_annotation[21:23, ]$x]

## make colour pallete
#pal_plot <- c(asex_ramp(170)[1,11,21,31,], bipot_ramp(3)[2], male_ramp(5)[3:4], female_ramp(5)[2:5])
pal_plot <- c(df_annotation$colour, '#49C16DFF')

## plot
umap_with_clusters <- DimPlot(tenx.justwt.integrated,
        group.by = "seurat_clusters_dot_plotting",
        dims = c(1,2), 
        reduction = "umap", 
        pt.size = 1,
        label.box = TRUE,
        label.size = 8,
        label.color = c(rep(c("#000000"), 12), rep(c("#ffffff"), 5), rep(c("#000000"), 2),"#ffffff", "#000000", "#ffffff", "#ffffff"),
        order = TRUE, 
        repel = TRUE, 
        label = TRUE,
        cols = pal_plot) +
  scale_color_manual(labels = c("Asexual 1", "Asexual 2" , "Asexual 3", "Asexual 4", "Asexual 5", "Asexual 6", "Asexual 7", "Asexual 8",  "Asexual 9", "Asexual 10", "Asexual 11", "Asexual 12", "Asexual 13", "Asexual 14", "Asexual 15", "Asexual 16", "Asexual 17", "Progenitor", "Male 1", "Male 2", "Female 1", "Female 2", "Female 3"), values = pal_plot) +
  theme_void() +
                     coord_fixed()
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
umap_with_clusters

save

ggsave("../images_to_export/umap_with_clusters.png", plot = umap_with_clusters, device = "png", path = NULL, scale = 1, width = 21, height = 29.5, units = "cm", dpi = 300, limitsize = TRUE)

dotplot

A dotplot allows us to look at the expression of multiple genes in a clearer way than succesive UMAP plots

### Data set-up

# PBANKA-0828000         GCSKO-3  GD1

# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-0413400    GCSKO-10_820  MD3
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-0102400         GCSKO-2  MD5 

# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-1435200        GCSKO-20  FD4 

# PBANKA-1437500 - AP2G - commitment
# PBANKA-1319500 - CCP2 - female - used in 820 line
# PBANKA-0416100 - MG1 - dynenin heavy chain - male - used in 820 line
# PBANKA-0831000 - MSP1 - late asexual
# PBANKA-1102200 - MSP8 - early asexual (from Bozdech paper)

marker_genes_list <- c("PBANKA-1437500", "PBANKA-1319500", "PBANKA-0416100", "PBANKA-0831000", "PBANKA-1102200")
mutant_genes_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0413400", "PBANKA-0716500", "PBANKA-0102400",  "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

## these get defined later on, but are replicated above here for plotting
asexual_early_clusters <- c(9, 4, 15, 8, 1, 14, 2, 10, 3, 0, 6, 5)
asexual_late_clusters <- c(7, 12, 18, 20, 23)
bipotentional_early_clusters <- # 0?
bipotential_clusters <- c(11) 
male_clusters <- c(16, 13)
female_clusters <- c(21, 22, 17, 19)

## copy the clusters so you don't permanently edit the master
tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting <- tenx.justwt.integrated@meta.data$seurat_clusters

## reorder the levels so you can plot the cluters as you wish
my_levels <- c(asexual_early_clusters,asexual_late_clusters, bipotential_clusters, male_clusters, female_clusters)

## reorder the levels
tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting <- factor(x = tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting, levels = my_levels)

## rename clusters so that they are intuitive
# this trick is from here: http://www.cookbook-r.com/Manipulating_data/Renaming_levels_of_a_factor/
levels(tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting) <- list(Asexual_1="9", 
                                                                              Asexual_2="4", 
                                                                              Asexual_3="15", 
                                                                              Asexual_4 = "8", 
                                                                              Asexual_5 = "1",
                                                                              Asexual_6=  "14", 
                                                                              Asexual_7 = "2", 
                                                                              Asexual_8 = "10",
                                                                              Asexual_9 = "3",
                                                                              Asexual_10 = "0",
                                                                              Asexual_11 = "6",
                                                                              Asexual_12 = "5",
                                                                              Asexual_13 = "7",
                                                                              Asexual_14 = "12",
                                                                              Asexual_15 = "18",
                                                                              Asexual_16 = "20",
                                                                              Asexual_17 = "23",
                                                                              Bipotential = "11",
                                                                              Male_1 = "16",
                                                                              Male_2 = "13",
                                                                              Female_1 = "21",
                                                                              Female_2 = "22",
                                                                              Female_3 = "19",
                                                                              Female_3 = "17"
                                                                              )

### Annotation set-up

## extract pseudotime numbers and identity of cells to a dataframe
df_pt_id <- tenx.justwt.integrated@meta.data[,c("old_pt_values", "monocle_sex", "seurat_clusters_dot_plotting", "Prediction.Spearman.", "Prediction.Spearman._Kasia")]

## make a new column
df_pt_id$colour <- NA

## assign bins to each of the values
## help here: https://stackoverflow.com/questions/9946630/colour-points-in-a-plot-differently-depending-on-a-vector-of-values 
df_pt_id[df_pt_id$monocle_sex == "Asexual_Early" | df_pt_id$monocle_sex == "Asexual_Late", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Asexual_Early" | df_pt_id$monocle_sex == "Asexual_Late", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Male", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Male", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Female", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Female", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Bipotential", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Bipotential", ]$old_pt_values,breaks = 100))

## make colour ramps
asex_ramp <- colorRampPalette(c("#D5E3F5", "#0052c5"))
male_ramp <- colorRampPalette(c("white", "yellow", "#016c00"))
female_ramp <- colorRampPalette(c("yellow", "#a52b1e"))
bipot_ramp <- colorRampPalette(c("white", "#ffe400"))

## assign values to each cluster
## take the mean of the bin
df_annotation <- aggregate(df_pt_id[, "colour"], list(df_pt_id$seurat_clusters_dot_plotting), mean)
## BECAUSE we have ordered the clusters already, we can simply take the row index for this bit
df_annotation$colour <- NA
df_annotation[1:17, ]$colour <- asex_ramp(100)[df_annotation[1:17, ]$x]
df_annotation[18, ]$colour <- bipot_ramp(100)[df_annotation[18, ]$x]
df_annotation[19:20, ]$colour <- male_ramp(100)[df_annotation[19:20, ]$x]
df_annotation[21:23, ]$colour <- female_ramp(100)[df_annotation[21:23, ]$x]

## plot annotation 
## this really helped: https://www.biostars.org/p/396810/
h2 <- ggplot(df_annotation)+
  geom_bar(mapping = aes(x = Group.1, y = 1), 
           stat = "identity",
           fill = df_annotation$colour,
           col = "#FFFFFF",
           width = 1)+
      theme_void()+
      theme(panel.spacing.x = unit(1, "mm"))#+
     #facet_grid(.~colour, scales = "free_x")
     #legend <- plot_grid(get_legend(h2), get_legend(h1), ncol = 1)
 h2 <- h2 + theme(legend.position = "none")
 #   geom_point(col = df_umap_plot$colour)
 
 h1 <- ggplot(df_annotation)+
  geom_point(mapping = aes(x = Group.1, y = 1),
            col = df_annotation$colour,
            size = 5)+
      theme_void()+
      theme(panel.spacing.x = unit(1, "mm"))#+
     #facet_grid(.~colour, scales = "free_x")
     #legend <- plot_grid(get_legend(h2), get_legend(h1), ncol = 1)
 h1 <- h1 + theme(legend.position = "none")
 #   geom_point(col = df_umap_plot$colour)

 ## add predicted time point
 ## take the mean of the bin
df_annotation <- aggregate(df_pt_id[, "Prediction.Spearman."], list(df_pt_id$seurat_clusters_dot_plotting), mean)
df_annotation$colour <- NA
df_annotation$colour <- viridis(300)[(df_annotation$x)*10]

h3 <- ggplot(df_annotation)+
  geom_bar(mapping = aes(x = Group.1, y = 1), 
           stat = "identity",
           fill = df_annotation$colour,
           col = "#FFFFFF",
           width = 1)+
      theme_void()+
      theme(panel.spacing.x = unit(1, "mm"))#+
     #facet_grid(.~colour, scales = "free_x")
     legend_h3 <- get_legend(h3)
 h3 <- h3 + theme(legend.position = "none")

  h3 <- ggplot(data = df_annotation, 
              mapping = aes(x = Group.1, fill=x)
              ) +
       geom_bar(col = "#FFFFFF", width = 1)+
       theme_void() +
       theme(panel.spacing.x = unit(1, "mm")) +
       scale_fill_viridis(option = 'cividis')
 legend_h3 <- get_legend(h3)
 h3 <- h3 + theme(legend.position = "none")
 
 ## add kasia data
  ## take the mean of the bin
df_annotation <- aggregate(df_pt_id[, "Prediction.Spearman._Kasia"], list(df_pt_id$seurat_clusters_dot_plotting), mean)
df_annotation$colour <- NA
df_annotation$colour <- viridis(300)[(df_annotation$x)*10]

h4 <- ggplot(df_annotation)+
  geom_bar(mapping = aes(x = Group.1, y = 1), 
           stat = "identity",
           fill = df_annotation$colour,
           col = "#FFFFFF",
           width = 1)+
      theme_void()+
      theme(panel.spacing.x = unit(1, "mm"))+
     facet_grid(.~colour, scales = "free_x")
     legend <- plot_grid(get_legend(h4), ncol = 1)
    legend_h4 <- get_legend(h4)
 h4 <- h4 + theme(legend.position = "none")

 h4 <- ggplot(data = df_annotation, 
              mapping = aes(x = Group.1, fill=x)
              ) +
       geom_bar(col = "#FFFFFF", width = 1)+
       theme_void() +
       theme(panel.spacing.x = unit(1, "mm")) +
       scale_fill_viridis()
 legend_h4 <- get_legend(h4)
 h4 <- h4 + theme(legend.position = "none")

### Plot
dot_plot_markers <- DotPlot(tenx.justwt.integrated, 
                            features = c(marker_genes_list, rev(mutant_genes_list)), 
                            group.by = "seurat_clusters_dot_plotting", 
                            dot.min = 0.00001,
                            assay = 'RNA') +
  theme_classic() +
  coord_fixed() +
  coord_flip() +
  # change appearance and remove axis elements, and make room for arrows
  theme(axis.text.x = element_text(size=16, angle = 45, hjust=1,vjust=1, family = "Arial"), 
        axis.text.y = element_text(size=16, face="italic"), 
        text=element_text(size=16, family="Arial", colour="black"), 
        legend.position = "bottom", 
        legend.direction = "horizontal", 
        legend.box = "vertical", 
        plot.title = element_blank(), 
        plot.margin = unit(c(1,3,1,3), "lines"), 
        axis.line = element_blank(),
        panel.border = element_rect(colour = "black", fill=NA, size=0.5)) +
  #change the colours
  #scale_colour_viridis(option = "inferno", guide = "colourbar", na.value="white", begin = 0, end = 1, direction = 1) +
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## change x axis label
  # labs(x = "Marker Genes", y = "Cluster", title = "Expression of Marker Genes by Cluster") 
  labs(x = "", y = "", title = "") +
  ## add arrows
  #annotate("segment", x = 5.5, xend = 5.5, y = 21.5, yend = 25, colour = "green", size=1, alpha=1, arrow=arrow(length=unit(0.30,"cm"), type = "closed")) +
  #annotate("segment", x = 5.5, xend = 5.5, y = 16.5, yend = 21.5, colour = "red", size=1, alpha=1, arrow=arrow(length=unit(0.30,"cm"), type = "closed")) +
  #annotate("segment", x = 5.5, xend = 5.5, y = 0, yend = 15.5, colour = "grey", size=1, alpha=1, arrow=arrow(length=unit(0.30,"cm"), type = "closed")) +
  ## annotate asex
  geom_hline(aes(yintercept = (length(c(asexual_early_clusters, asexual_late_clusters))+0.5)), size = 0.5, linetype= 'dashed') +
  ## annotate bipotential
  geom_hline(aes(yintercept = (length(c(asexual_early_clusters, asexual_late_clusters, bipotential_clusters))+0.5)), size = 0.5, linetype= 'dashed') +
  ## annotate sexes
  geom_hline(aes(yintercept = (length(c(asexual_early_clusters, asexual_late_clusters, bipotential_clusters, male_clusters))+0.5)), size = 0.5, linetype= 'dashed') +
  ## change label on bottom of plot so we can indicate markers
  scale_x_discrete(labels = rev(c("gd1", "md1", "md2", "md3", "md4", "md5", "fd1", "fd2", "fd3", "fd4", "msp8", "msp1", "mg1", "ccp2", "ap2g"))) +
  ## change label on bottom of plot so we can indicate markers
  scale_y_discrete(labels = c("Asexual 1", "Asexual 2" , "Asexual 3", "Asexual 4", "Asexual 5", "Asexual 6", "Asexual 7", "Asexual 8",  "Asexual 9", "Asexual 10", "Asexual 11", "Asexual 12", "Asexual 13", "Asexual 14", "Asexual 15", "Asexual 16", "Asexual 17", "Progenitor", "Male 1", "Male 2", "Female 1", "Female 2", "Female 3")) +
  ## change name of legends
  guides(col=guide_colorbar(title = 'Scaled Average Expression'),
         size=guide_legend("% of cells expressing"))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
## view
#print(dot_plot_markers)

plot <- plot_grid(h4, h3, h1, dot_plot_markers, align = "v", ncol = 1, axis = "tb", rel_heights = c(0.5, 0.5, 0.5, 18)) 
Removed 37 rows containing missing values (geom_point).font family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font database
dot_plot <- plot_grid(plot, legend_h3, legend_h4, nrow = 1, rel_widths = c(10, 1.5, 1.5))

dot_plot

save

ggsave("../images_to_export/dot_plot_all.png", plot = dot_plot, device = "png", path = NULL, scale = 1, width = 29.7, height = 21, units = "cm", dpi = 300, limitsize = TRUE)

9. Subset sexual cells

Make a subsetted Seurat object of sexual cells.

Include the pre-branch too as well as any weird clusters that may have clustered out.

it’s been a while since we looked at the clusters so let’s check them out again:

## Plot
DimPlot(tenx.justwt.integrated, label = TRUE, repel = FALSE, pt.size = 0.05, group.by = "seurat_clusters", dims = c(1,2), reduction = "umap") + coord_fixed()

## plot
list_UMAPs_by_cluster[[1]] + list_UMAPs_by_cluster[[2]] + list_UMAPs_by_cluster[[3]] + list_UMAPs_by_cluster[[4]] + list_UMAPs_by_cluster[[5]] + list_UMAPs_by_cluster[[6]] + list_UMAPs_by_cluster[[7]] + list_UMAPs_by_cluster[[8]] + list_UMAPs_by_cluster[[9]] + list_UMAPs_by_cluster[[10]] + list_UMAPs_by_cluster[[11]] + list_UMAPs_by_cluster[[12]] + list_UMAPs_by_cluster[[13]] + list_UMAPs_by_cluster[[14]] + list_UMAPs_by_cluster[[15]] + list_UMAPs_by_cluster[[16]] + list_UMAPs_by_cluster[[17]] + list_UMAPs_by_cluster[[18]] + list_UMAPs_by_cluster[[19]] + list_UMAPs_by_cluster[[20]] + list_UMAPs_by_cluster[[21]] + list_UMAPs_by_cluster[[22]] + list_UMAPs_by_cluster[[23]] + list_UMAPs_by_cluster[[24]]

Define cells and subset

asexual_early_clusters <- c(9, 4, 15, 8, 1, 14, 2, 10, 3, 0, 6, 5)
asexual_late_clusters <- c(7, 12, 18, 20, 23)
bipotentional_early_clusters <- # 0?
bipotential_clusters <- c(11) 
male_clusters <- c(16, 13)
female_clusters <- c(21, 22, 17, 19)

## define cells
cell_names_subset_monocle_ids <- rownames(tenx.justwt.integrated@meta.data[tenx.justwt.integrated@meta.data$monocle_sex %in% c("Asexual_Early", "Bipotential", "Male", "Female"), ])

## 3, 0, 6, 5 are early clusters of asexuals before the branch
cell_names_subset_cluster_ids <- rownames(tenx.justwt.integrated@meta.data[tenx.justwt.integrated@meta.data$seurat_clusters %in% c(male_clusters, female_clusters, bipotential_clusters, 3, 0, 6, 5), ])

cell_names_subset_intersect <- intersect(cell_names_subset_monocle_ids, cell_names_subset_cluster_ids)

## subset cells into new object
tenx.justwt.integrated.sex <- subset(tenx.justwt.integrated, cells = cell_names_subset_intersect)

inspect/check

## inspect object
tenx.justwt.integrated.sex

## look at original UMAP
DimPlot(tenx.justwt.integrated.sex, label = TRUE, repel = TRUE, pt.size = 0.1, split.by = "experiment", dims = c(1,2), reduction = "umap") + coord_fixed()

Remove contaminant asexual cells

we want to remove:

## look at original UMAP
plot_sexual_subsetting <- DimPlot(tenx.justwt.integrated.sex, label = TRUE, repel = TRUE, pt.size = 0.1, dims = c(1,2), reduction = "umap") + 
  coord_fixed() + 
  geom_vline(aes(xintercept = -1, alpha = 5))

plot_sexual_subsetting
## extract cell embeddings
df_sex_cell_embeddings <- as.data.frame(tenx.justwt.integrated.sex@reductions[["umap"]]@cell.embeddings)

## subset anything lower than -0.8 in UMAP 2 and -0.1 in UMAP 1
remove_cells <- row.names(df_sex_cell_embeddings[which(df_sex_cell_embeddings$UMAP_1 < -1), ])

## plot these cells
DimPlot(tenx.justwt.integrated.sex, label = FALSE, repel = TRUE, pt.size = 0.1, cells.highlight = remove_cells, dims = c(1,2), reduction = "umap") + 
  coord_fixed() + 
  scale_color_manual(values=c("#000000", "#f54e1e")) + 
  theme_void() + 
  labs(title = paste("cells highlighted will be removed")) + 
  theme(plot.title = element_text(hjust = 0.5), legend.position = "none")

Final Subset

tenx.justwt.integrated.sex
An object of class Seurat 
10116 features across 2817 samples within 2 assays 
Active assay: RNA (5098 features, 0 variable features)
 1 other assay present: integrated
 2 dimensional reductions calculated: pca, umap

copy old clusters over

## copy old clusters
tenx.justwt.integrated.sex <- AddMetaData(tenx.justwt.integrated.sex, tenx.justwt.integrated.sex@meta.data$seurat_clusters, col.name = "post_integration_clusters")

10. Sex assignment of mutants

A. Seurat Method

## find transfer anchors
DefaultAssay(tenx.justwt.integrated) <- "integrated"
merge.anchors <- FindTransferAnchors(reference = tenx.justwt.integrated, query = GCSKO_mutants, 
    dims = 1:30)
Performing PCA on the provided reference using 2000 features as input.
Projecting PCA
Finding neighborhoods
Finding anchors
    Found 920 anchors
Filtering anchors
    Retained 610 anchors
## transfer data between ref and query
predictions <- TransferData(anchorset = merge.anchors, refdata = tenx.justwt.integrated$seurat_clusters_dot_plotting, 
    dims = 1:30)
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Predicting cell labels
## add meta data to object
GCSKO_mutants <- AddMetaData(GCSKO_mutants, metadata = predictions)

## new object from this
mutant_seurat <- GCSKO_mutants

## look at breakdown of mutant by designation
df <- as.data.frame(mutant_seurat@meta.data)
table(df$predicted.id, df$identity_name_updated)
            
             fd1 fd2 fd3 fd4 gd1 md1 md2 md3 md4 md5 wild-type
  Asexual_1    2  43   5   7  10   4   4   6   5  42        37
  Asexual_10   6  29   5   4   9   3   9  10   1  27        42
  Asexual_12   0   1   0   0   1   1   1   0   0   0         0
  Asexual_13   2   4  10   1  35  10   4  32   5   0        15
  Asexual_14   1   3  17   3  40  25   8  15   8   4        40
  Asexual_15  19   6  19   2  24  10   4  25   6   2        25
  Asexual_16  27  13  30   4  33  49  13  75   8  14        63
  Asexual_17  10  23  15   4  13  25  13  38  12  19        48
  Female_1     2  51   5   0   6  23  64   2   1   4        37
  Female_3    19  11  14  23   0 105 141  86  14  21       160
  Male_1       0   1   0   0  48   0   0   2   9   1         2
  Male_2      65  55  14  45  14   0   0  45   8 112       220
## see how this overlaps with fluorescence sorted on for 820 to confirm accuracy
df_820 <- df[df$genetic_background =="PBANKA_820", ]
table(df_820$predicted.id, df_820$fluoresence_sorted_on)
               
                GFP Hoechst mCherry
  Asexual_Early   0      69       1
  Asexual_Late   33     459      16
  Female          2     342     240
  Male          182      49       0

inspect gd1

df[which(df$predicted.id == "Female_1" & df$identity_name_updated == "gd1"), ][, 118:146]

Calculate sex ratios

## use designations above for sexes
male_cells <- rownames(mutant_seurat@meta.data[mutant_seurat@meta.data$predicted.id == "Male", ])
female_cells <- rownames(mutant_seurat@meta.data[mutant_seurat@meta.data$predicted.id == "Female", ])
ss2_mutants_final_male <- subset(mutant_seurat, cells = male_cells)
ss2_mutants_final_female <- subset(mutant_seurat, cells = female_cells)

## inspect
ss2_mutants_final_male
An object of class Seurat 
5018 features across 636 samples within 1 assay 
Active assay: RNA (5018 features, 0 variable features)
ss2_mutants_final_female
An object of class Seurat 
5018 features across 788 samples within 1 assay 
Active assay: RNA (5018 features, 0 variable features)
## calculate sex ratios
##subset out H, sorted cells:
df_male <- ss2_mutants_final_male@meta.data[ss2_mutants_final_male@meta.data$exclude_for_sex_ratio == FALSE,]

dim(df_male)
[1] 454 124
df_female <- ss2_mutants_final_female@meta.data[ss2_mutants_final_female@meta.data$exclude_for_sex_ratio == FALSE,]

dim(df_female)
[1] 546 124
## make dataframe
df_sex_ratio <- merge(
  as.data.frame(table(df_male$sub_name_updated)), 
  as.data.frame(table(df_female$sub_name_updated)), 
  by = "Var1", all=TRUE)

# or use identity_updated

## add names
names(df_sex_ratio) <- c("genotype", "male", "female")

## change the NAs to 0
df_sex_ratio[is.na(df_sex_ratio)] <- 0

## collapse 820 wild-types together
combined_m <- df_sex_ratio[df_sex_ratio$genotype == "WT-820_3_5", ]$male + df_sex_ratio[df_sex_ratio$genotype == "WT-820", ]$male
combined_f <- df_sex_ratio[df_sex_ratio$genotype == "WT-820_3_5", ]$female + df_sex_ratio[df_sex_ratio$genotype == "WT-820", ]$female
df_sex_ratio <- rbind(df_sex_ratio, c("WT-820-combined", combined_m, combined_f))
invalid factor level, NA generated
# remove old rows
df_sex_ratio <- df_sex_ratio[-which(df_sex_ratio$genotype == "WT-820_3_5" | df_sex_ratio$genotype == "WT-820"), ]
# need to make numeric again
df_sex_ratio$male <- as.numeric(df_sex_ratio$male)
df_sex_ratio$female <- as.numeric(df_sex_ratio$female)
df_sex_ratio$genotype <- as.character(df_sex_ratio$genotype)
# add name for WT combined
df_sex_ratio$genotype[17] <- "WT-820-combined"

## calculate sex ratio
df_sex_ratio$sex_ratio <- (df_sex_ratio$male + 0.1)/(df_sex_ratio$female + 0.1)

## log sex ratio
df_sex_ratio$sex_ratio_log <- log10(df_sex_ratio$sex_ratio)

##view
df_sex_ratio
## remove WT-2 because it is really inappropriate to have a sex ratio for this:
df_sex_ratio <- df_sex_ratio[-which(df_sex_ratio$genotype == "WT-md5"),]

plot

B. SCMAP Method

Build the index

### Making an ortholog reference index

## load in mca data
#counts <- read.csv("../scmap/allpb10x_counts.csv", row.names = 1)
#pheno <- read.csv("../scmap/allpb10x_pheno.csv")
#ggplot(pheno, aes(x=PC2_3d, y = PC3_3d,colour=absclust3)) + geom_point()

## load required libraries
library(scmap) #https://bioconductor.org/packages/release/bioc/html/scmap.html 
library(SingleCellExperiment) #

#prep the SCE, if was originally a Suerat object need the dfs to be regular matrices
#pb_filtered_sce_orth <- pb_filtered_sce_orth[, colData(pb_filtered_sce_orth)$absclust3 != "8"]
#sce <- pb_filtered_sce_orth
#pca <- plotPCA(sce)
#pcs <- pca$data
#table(rownames(pcs)==colnames(sce))
#colData(sce) <- cbind(colData(sce), pcs)
#rowData(sce)$feature_symbol <- rowData(sce)$gene

## extract data from Seurat
#cells_tenx <- rownames(tenx.justwt.integrated@meta.data[which(tenx.justwt.integrated@meta.data$experiment == "tenx_5k"), ])
#tenx.justwt.integrated.10k <- subset(tenx.justwt.integrated, cells = cells_tenx)
counts = as.matrix(GetAssayData(tenx.justwt.integrated, slot = "counts", assay = "RNA"))
pheno = as.data.frame(tenx.justwt.integrated@meta.data)

## add UMAP coordinates
df_sex_cell_embeddings <- as.data.frame(tenx.justwt.integrated@reductions[["umap"]]@cell.embeddings)
pheno <- cbind(pheno, df_sex_cell_embeddings)

## Set up object
sce <- SingleCellExperiment(list(counts=counts),
    colData=DataFrame(label=pheno),
    rowData=DataFrame(feature_symbol=rownames(counts)))
sce
class: SingleCellExperiment 
dim: 5098 6880 
metadata(0):
assays(1): counts
rownames(5098): PBANKA-0000101 PBANKA-0000301 ... PBANKA-MIT0360 PBANKA-MIT0370
rowData names(1): feature_symbol
colnames(6880): AAACCTGGTAAGGGCT AAACCTGGTGCACTTA ... SC25027_8_95 SC25027_8_96
colData names(127): label.orig.ident label.nCount_RNA ... label.UMAP_1 label.UMAP_2
reducedDimNames(0):
altExpNames(0):
## manual logging
#counts_1 <- assay(sce, "counts")
#libsizes <- colSums(counts_1)
#size.factors <- libsizes/mean(libsizes)
#logcounts(sce) <- log2(t(t(counts_1)/size.factors) + 1)
#counts(sce) <- as.matrix(counts(sce))
#logcounts(sce) <- as.matrix(logcounts(sce))
logcounts(sce) <- as.matrix(GetAssayData(tenx.justwt.integrated, slot = "data", assay = "RNA"))

## remove features with duplicated names
sce <- sce[!duplicated(rownames(sce)), ]

## build scmap-cell reference index, save this rds
sce <- selectFeatures(sce, suppress_plot = FALSE, n_features = 2000)

table(rowData(sce)$scmap_features)

FALSE  TRUE 
 3098  2000 
set.seed(1)
sce <- indexCell(sce, M = 50, k = 80)
names(metadata(sce)$scmap_cell_index)
[1] "subcentroids" "subclusters" 
length(metadata(sce)$scmap_cell_index$subcentroids)
[1] 50
dim(metadata(sce)$scmap_cell_index$subcentroids[[1]])
[1] 40 80
metadata(sce)$scmap_cell_index$subcentroids[[1]][,1:5]
                        1           2           3           4          5
PBANKA-0100200 0.14630862 0.526027391 0.043704597 0.084187544 0.27749519
PBANKA-0100700 0.09460507 0.073257106 0.313286733 0.370676472 0.27852452
PBANKA-0100900 0.09923532 0.087566303 0.059203198 0.094759828 0.06865377
PBANKA-0101000 0.04763362 0.033790484 0.035038280 0.029494053 0.09082912
PBANKA-0101200 0.05167727 0.100910226 0.041157644 0.087829422 0.04947390
PBANKA-0101300 0.03427392 0.000000000 0.006482623 0.017440407 0.04685456
PBANKA-0101400 0.12483604 0.023321169 0.056473567 0.214402432 0.30191506
PBANKA-0101500 0.03194160 0.050889592 0.037542520 0.040676819 0.02895481
PBANKA-0101600 0.03798147 0.007504403 0.028087301 0.055265292 0.02882148
PBANKA-0101800 0.28129376 0.098383830 0.133405404 0.110619710 0.08911439
PBANKA-0101900 0.04066573 0.007504403 0.033564638 0.036681755 0.18011835
PBANKA-0102000 0.07611798 0.066861770 0.012354195 0.077811108 0.09136082
PBANKA-0102200 0.06226485 0.251753986 0.605044037 0.076494250 0.11263897
PBANKA-0102800 0.06418848 0.030164171 0.042579458 0.058224917 0.09315054
PBANKA-0103100 0.11743208 0.010838894 0.026223349 0.027978543 0.07163404
PBANKA-0103800 0.04052086 0.092749297 0.037663604 0.051866920 0.05463320
PBANKA-0104100 0.10698392 0.000000000 0.000000000 0.021640058 0.01323152
PBANKA-0104900 0.15330358 0.040643918 0.047150266 0.096686040 0.08016202
PBANKA-0105100 0.00774803 0.000000000 0.000000000 0.000000000 0.01212389
PBANKA-0105200 0.14295074 0.090669292 0.195180247 0.390381118 0.10203677
PBANKA-0105300 0.07266638 0.035247576 0.083080416 0.026830263 0.08893071
PBANKA-0105500 0.05972304 0.130442176 0.613873789 0.124039039 0.06698287
PBANKA-0105600 0.10822754 0.303080159 0.124325455 0.169514333 0.18211011
PBANKA-0106100 0.08682023 0.000000000 0.037839217 0.049002485 0.05906248
PBANKA-0106300 0.01815899 0.000000000 0.007580943 0.002964005 0.01617340
PBANKA-0106500 0.06709366 0.160165980 0.103227974 0.026045686 0.29711821
PBANKA-0106600 0.06615049 0.041341810 0.011974030 0.090413046 0.08166804
PBANKA-0106900 0.06772833 0.099129853 0.058992669 0.401040855 0.09974455
PBANKA-0106950 0.07031790 0.010838894 0.008323748 0.062299847 0.04044479
PBANKA-0107100 0.17579265 0.059474584 0.032474136 0.119798580 0.10795614
PBANKA-0107300 0.52569711 0.140088244 0.000000000 0.452049173 0.43157921
PBANKA-0107400 0.40027934 0.554030211 0.028538986 0.179514374 0.30285506
PBANKA-0107500 0.06729382 0.074821209 0.023884962 0.041973749 0.10242388
PBANKA-0107600 0.10346987 0.295645683 0.107376132 0.291553393 0.09681055
PBANKA-0108200 0.10862989 0.032331520 0.101822888 0.088844686 0.07713661
PBANKA-0108500 0.02145669 0.030583685 0.024050668 0.031126013 0.02086511
PBANKA-0108600 0.24498462 0.045568380 0.056630631 0.095147870 0.18860540
PBANKA-0108700 0.39883605 0.152992706 0.123346730 0.108083282 0.35455198
PBANKA-0108800 0.08791660 0.022213910 0.000000000 0.016375691 0.04375594
PBANKA-0108900 0.03944358 0.012735216 0.017821829 0.063455344 0.06855602
dim(metadata(sce)$scmap_cell_index$subclusters)
[1]   50 6880
#saveRDS(pb_filtered_sce_orth, file="pb_filtered_sce_orthindex_20181109.rds")

Map to the index

scmapCell_results$wt$cells[, 1:3]
      SC26779_5_100 SC26779_5_101 SC26779_5_102
 [1,]          6554          6685          6163
 [2,]          6247          6528          6200
 [3,]          6734          6436          6466
 [4,]          6323          6588          6124
 [5,]          6468          6470          6871
 [6,]          6685          6323          6563
 [7,]          6470          6606          6456
 [8,]          6436          6614          6149
 [9,]          6515          6608          6494
[10,]          6614          6854          6647
## get cell indexes 
getcells <- scmapCell_results$wt$cells[1, ]
## exctract cells metadata from index
cdsce <- colData(sce)[getcells, ]
## extract similarities
topsim <- scmapCell_results$wt$similarities[1, ]
## get name of top cell matched
mutants.sce$topcell <- rownames(cdsce)
## get sex id
mutants.sce$topcell_ac <- cdsce$label.monocle_sex
## get coordinates of matched cell
mutants.sce$indexPC1 <- cdsce$label.UMAP_1
mutants.sce$indexPC2 <- cdsce$label.UMAP_2
#mutants.sce$pbpt <- cdsce$pseudotime
#mutants.sce$pbbulk <- cdsce$bulk
mutants.sce$topcell_sp <- mutants.sce$topcell_ac
mutants.sce$topsim <- topsim
mutants.sce$topcell_sp[mutants.sce$topsim < 0.4] <- "unassigned"
table(mutants.sce$topcell_sp)

Asexual_Early  Asexual_Late        Female          Male    unassigned 
          335           346           186           548          1302 
## see how this overlaps with fluorescence sorted on for 820 to confirm accuracy
df_820 <- colData(mutants.sce)[colData(mutants.sce)$label.genetic_background =="PBANKA_820", ]
table(df_820$topcell_sp, df_820$label.fluoresence_sorted_on)
               
                GFP Hoechst mCherry
  Asexual_Early   0      89       2
  Asexual_Late    5     150       3
  Female          2      84      54
  Male          158      47       0
  unassigned     52     549     198
table(colData(mutants.sce)$topcell_sp, colData(mutants.sce)$label.identity_name_updated)
               
                fd1 fd2 fd3 fd4 gd1 md1 md2 md3 md4 md5 wild-type
  Asexual_Early   9  74  13   9  20  12  17  20   8  67        86
  Asexual_Late   14  21  37   8  36  45  21  43  20  22        79
  Female          1   2   7   2   0  17  39  44   3   6        65
  Male           64  51  14  41  25   0   0  34  12 104       203
  unassigned     65  92  63  33 152 181 184 195  34  47       256
#### TOP 3NN method

#This function makes a list of the PC means for each cell and then do.call below rbinds them into a dataframe called big_data

datalist = list()

for (i in colnames(scmapCell_results$wt$cells)) {
  
  getcellstest <- scmapCell_results$wt$cells[1:3, i]
  cdscetest <- colData(sce)[getcellstest, ]
  PC1mean <- mean(cdscetest$label.UMAP_1)
  PC2mean <- mean(cdscetest$label.UMAP_2)
  # ... make some data
  dat <- data.frame(i, PC1mean, PC2mean)
  dat$i <- i  # maybe you want to keep track of which iteration produced it?
  datalist[[i]] <- dat # add it to your list
}

big_data = do.call(rbind, datalist)
# or big_data <- dplyr::bind_rows(datalist)
# or big_data <- data.table::rbindlist(datalist)

test <- big_data[1, ]

df <- data.frame(X=colData(sce)$label.UMAP_1, Y=colData(sce)$label.UMAP_2, row.names = rownames(colData(sce)))

#the snap function snaps to the nearest cell in PC coordiantes
snap <- function(df, test){
  require(Biobase)
  d <- matchpt(as.matrix(df),
               as.matrix(data.frame(X=test$PC1mean,Y=test$PC2mean)))
  
  min_row <- rownames(d[d$distance==min(d$distance),])
  
  test$X_snap <- unique(df[min_row,"X"])
  test$Y_snap <- unique(df[min_row,"Y"])
  test$pb_cell <- min_row
  
  test
}

#this loops through each cell and in big_data and runs the snap function
datalist2 = list()
colnames(big_data) <- c("sample_id", "PC1mean", "PC2mean")
for (i in rownames(big_data)) {
  test <- big_data[i, ]
  coord <- snap(df, test)
  coord$i <- i
  datalist2[[i]] <- coord
}
big_data2 = do.call(rbind, datalist2)


table(rownames(big_data2)==rownames(colData(mutants.sce)))

TRUE 
2717 
allpbcd <- colData(sce)
allpbcd <- as.data.frame(allpbcd)
pbabsclust <- allpbcd[, c("label.pt_id_cols", "label.identity_name_updated", "label.monocle_sex"), drop=FALSE]
pbabsclust$pb_sample_id <- rownames(pbabsclust)

# Now merge the pc cell asignments with their abs clust and get in the right order
big_data3 <- merge(big_data2, pbabsclust, by.x = "pb_cell", by.y = "pb_sample_id", all.x=TRUE, all.y=FALSE)
big_data4 <- big_data3[match(rownames(big_data2), big_data3$sample_id), ]


colors <- c("6"="#78C679",
            "2"="#D1EC9F",
            "0"="#FEB24C",
            "1"="#F4CF63",
            "3"="#FEEEAA",
            "4"="#85B1D3",
            "7"="#9ecae1",
            "5"="#C9E8F1",
            "M"= "#B7B7D8",
            "F"="#9C96C6",
            "unassigned"="black")

ggplot(big_data4, aes(PC1mean, PC2mean)) +
  geom_point(col = big_data4$label.pt_id_cols) +
                     theme_void() +
                     coord_fixed()


#+ geom_point(aes(colour=factor(big_data4$label.label.pt_id_cols))) + scale_color_manual(values = colors) 

                     

ggplot(big_data4, aes(X_snap, Y_snap)) +
  geom_point(col = big_data4$label.pt_id_cols) +
                     theme_void() +
                     coord_fixed() 


#+ geom_point(aes(colour=factor(big_data4$label.label.pt_id_cols))) + scale_color_manual(values = colors) 

##add info to SCE and save colData, to be an assigned cell all 3NN must have a cos sim >0.4
scmapCell_results$wt$similarities[, 1:3]
      SC26779_5_100 SC26779_5_101 SC26779_5_102
 [1,]     0.2654243     0.3283723     0.4455592
 [2,]     0.2657229     0.3322655     0.4476295
 [3,]     0.2649363     0.3346425     0.4463425
 [4,]     0.2685002     0.3314723     0.4455779
 [5,]     0.2655940     0.3347640     0.4463982
 [6,]     0.2654118     0.3351348     0.4472700
 [7,]     0.2659329     0.3289516     0.4482864
 [8,]     0.2683255     0.3303473     0.4451670
 [9,]     0.2668498     0.3284948     0.4503529
[10,]     0.2664087     0.3284307     0.4486978
topsim1 <- scmapCell_results$wt$similarities[1, ]
topsim2 <- scmapCell_results$wt$similarities[2, ]
topsim3 <- scmapCell_results$wt$similarities[3, ]

table(big_data4$sample_id==rownames(colData(mutants.sce)))

TRUE 
2717 
#pfobj$pb_cell <- big_data4$pb_cell
#pfobj$PC1mean <- big_data4$PC1mean
bd4 <- big_data4[, c("pb_cell", "sample_id", "PC1mean", "PC2mean", "X_snap", "Y_snap", "label.pt_id_cols", "label.identity_name_updated", "label.monocle_sex")]

colData(mutants.sce) <- cbind(colData(mutants.sce), bd4)

mutants.sce$topsim1 <- topsim1
mutants.sce$topsim2 <- topsim2
mutants.sce$topsim3 <- topsim3
mutants.sce$stage_pred <- big_data4$label.monocle_sex
mutants.sce$stage_pred[mutants.sce$topsim1 < 0.4 | mutants.sce$topsim2 < 0.4 | mutants.sce$topsim3 < 0.4] <- "unassigned"
table(mutants.sce$stage_pred)

Asexual_Early  Asexual_Late   Bipotential        Female          Male    unassigned 
          325           345             1           182           546          1318 
#write.csv(bd4, "pfcellassignmentswithmean3nn_20181029.csv")
#write.csv(colData(pfobj), "pf3d7100scmapclusts2methodindexn100_20190107.csv")
## see how this overlaps with fluorescence sorted on for 820 to confirm accuracy
df_820 <- colData(mutants.sce)[colData(mutants.sce)$label.genetic_background =="PBANKA_820", ]
table(df_820$stage_pred, df_820$label.fluoresence_sorted_on)
               
                GFP Hoechst mCherry
  Asexual_Early   1      81       2
  Asexual_Late    3     153       3
  Bipotential     0       1       0
  Female          2      83      52
  Male          156      47       0
  unassigned     55     554     200
table(colData(mutants.sce)$stage_pred, colData(mutants.sce)$label.identity_name_updated)
               
                fd1 fd2 fd3 fd4 gd1 md1 md2 md3 md4 md5 wild-type
  Asexual_Early   7  73  11   9  20  10  15  20   7  68        85
  Asexual_Late   16  22  39   8  34  46  23  41  20  21        75
  Bipotential     0   0   0   0   0   0   0   0   0   0         1
  Female          1   2   7   2   0  16  39  44   3   6        62
  Male           64  51  14  41  25   0   0  33  12 104       202
  unassigned     65  92  63  33 154 183 184 198  35  47       264

make final plot with MCA data below

## Read in MCA data
pheno <- read.csv("../scmap/allpb10x_pheno.csv")
## extract rows needed for plotting
df_plot <- pheno[,c("PC2_3d", "PC3_3d", "absclust3")]
df_plot$experiment <- df_plot$absclust3

## extract rows needed for plotting from mapped object
df_plot_pm <- as.data.frame(colData(pm_ss2_field.sce.orth))
df_plot_pm <- df_plot_pm[ ,c("X_snap", "Y_snap", "label.absclust3")]
df_plot_pm$experiment <- "pm"
colnames(df_plot_pm) <- c("PC2_3d", "PC3_3d", "absclust3", "experiment")

## extract rows needed for plotting from mapped object
df_plot_pf <- as.data.frame(colData(pf_ss2_field.sce.orth))
df_plot_pf <- df_plot_pf[ ,c("X_snap", "Y_snap", "label.absclust3")]
df_plot_pf$experiment <- "pf"
colnames(df_plot_pf) <- c("PC2_3d", "PC3_3d", "absclust3", "experiment")

## bind together
df_plot <- rbind(df_plot, df_plot_pf, df_plot_pm)

colors <- c("6"="#78C679",
            "2"="#D1EC9F",
            "0"="#FEB24C",
            "1"="#F4CF63",
            "3"="#FEEEAA",
            "4"="#85B1D3",
            "7"="#9ecae1",
            "5"="#C9E8F1",
            "M"= "#B7B7D8",
            "F"="#9C96C6",
            "unassigned"="black",
            "pm" = "#dc65a4",
            "pf" = "#24245f")

## add alpha for plotting
df_plot$alpha[!df_plot$experiment == "pm"] <- 0.5
df_plot$alpha[df_plot$experiment == "pm"] <- 1
df_plot$alpha[df_plot$experiment == "pf"] <- 1

##plot
scmap_pca <- ggplot(df_plot, aes(x=PC2_3d, y = PC3_3d,colour=experiment, alpha = alpha)) + 
  geom_point() +
  theme_void() +
  scale_color_manual(values = colors) +
  ## remove alpha scale
  scale_alpha_continuous(guide=FALSE)
  ## draw ring around field samples
  #geom_point(data=df_plot[df_plot$experiment == "pm", ], pch=21, fill=NA, size=2, colour="black", stroke=1) +
  ## make non-field samples more opaque
  #geom_point(data=df_plot[-df_plot$experiment == "pm", ], alpha = 0.2)

## view
scmap_pca_2 <- scmap_pca + 
  guides(colour=guide_legend(override.aes = list(size=4)))

scmap_pca_2

save

#ggsave("../images_to_export/field_samples_scmap.png", plot = scmap_pca_2, device = "png", path = NULL, scale = 1, width = 15, height = 10, units = "cm", dpi = 300, limitsize = TRUE)

Overlap and validation

11. Save and Export

save

Save environment

## This saves everything in the global environment for easy recall later
#save.image(file = "GCSKO_merge.RData")
#load(file = "GCSKO_merge.RData")

Save object(s)

## Save an object to a file
saveRDS(tenx.justwt.integrated.sex, file = "../data_to_export/tenx.justwt.integrated.sex.RDS")
## Restore the object
#readRDS(file = "../data_to_export/tenx.mutant.integrated.sex.RDS")

## save integrated object to file
saveRDS(tenx.justwt.integrated, file = "../data_to_export/tenx.justwt.integrated.RDS") 
## restore the object
#tenx.justwt.integrated <- readRDS("../data_to_export/tenx.justwt.integrated.RDS")

## save monocle object
saveRDS(monocle.object.all, file = "../data_to_export/monocle.object.all.RDS") 
## restore the object
#monocle.object.all <- readRDS("../data_to_export/monocle.object.all.RDS")

## save integrated object to file
#saveRDS(GCSKO_mutants, file = "../data_to_export/GCSKO_mutants.RDS") 
## restore the object
#tenx.justwt.integrated <- readRDS("../data_to_export/tenx.justwt.integrated.RDS")

## extract UMAP coordinates and metadata
## extract metadata
mca_website_df <- tenx.justwt.integrated@meta.data

## add umap - merge on row names and then make sure row names are not dropped or added
mca_website_df <- transform(merge(mca_website_df, tenx.justwt.integrated@reductions[["umap"]]@cell.embeddings, by=0, all=TRUE), row.names=Row.names, Row.names=NULL)

## send this to sunil:
# ggplot(mca_website_df, aes(x = UMAP_1, y = UMAP_2)) +
# geom_point(col = mca_website_df$pt_id_cols) +
# theme_void() +
# coord_fixed()

## export
write.csv(mca_website_df, file = "../data_to_export/mca_website_df.csv")

Clean up

#rm(ss2_wt_cells)
#rm(tenx.justwt.integrated)
#rm(tenx.justwt.list)

final figure construction

Cowplot(plot_grid), patchwork(wrap_plots), and ggpubr can all allow multiple plots to be plotted together.

## A
# umap_id_pt
## B
# marker gene expression
## C
# Mutant gene expression
## D
# Modules

#Figure_A <- grid.arrange(arrangeGrob(QC_composite_plot, QC_mito_violin, QC_mito_graph, QC_by_genotype, mapping_rate_plot), nrow=3), nrow=2, heights=c(10,2))

## cowplot method
## can use this for labels: toupper(letters)[1:10]

## C. Mutant genes
mutant_genes_figure <- plot_grid(
                                 ## marker genes starts
                                 marker_gene_plot_FAMB,
                                 marker_gene_plot_MSP8,
                                 marker_gene_plot_MSP1,
                                 marker_gene_plot_AP2G,
                                 marker_gene_plot_CCP2,
                                 marker_gene_plot_MG1,
                                 ## mutant genes starts  
                                 marker_gene_plot_gd1,
                                 marker_gene_plot_md1,
                                 marker_gene_plot_md2,
                                 marker_gene_plot_md3,
                                 marker_gene_plot_md4, 
                                 marker_gene_plot_md5,
                                 marker_gene_plot_fd1,
                                 marker_gene_plot_fd2,
                                 marker_gene_plot_fd3,
                                 marker_gene_plot_fd4, 
  label_size = 1, 
  nrow = 4)

## labels as uppercase letters:
#c(toupper(letters)[2:17])
# labels as roman numerals:
# c(tolower(as.roman(c(2:17))

Figure_publication <- plot_grid(umap_id_pt + theme(plot.margin = unit(c(0, 0, 0, 0), "cm")), 
                                mutant_genes_figure,
                                ## add empty plot to give spacing
                                ggplot() + theme_void(),
                                labels = c('A', 'B'), 
                                label_size = 12, 
                                ncol = 2, 
                                nrow=2, 
                                rel_heights = c(1, 1, 4), 
                                rel_widths = c(1, 2, 3))

Figure_publication

save

ggsave("../images_to_export/Figure_C.png", plot = Figure_publication, device = "png", path = NULL, scale = 1, width = 21, height = 29.7, units = "cm", dpi = 300, limitsize = TRUE)
layout <- "
AAABBB
CCDDEE
FFGGHH
IIJJKK
"

Figure_publication_A <- (composition_umap_10x + theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 10))) +
(composition_umap_ss2 + theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 10))) + 
plot_layout(ncol = 2)

Figure_publication <- Figure_publication_A +
#(UMAP_hoo + theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 10)) + labs(title="Predicted Asexual Cycle Real Timepoint")) +
#(UMAP_kasia + theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 10)) + labs(title="Predicted Gametocytogenesis Real Timepoint")) +
  ## marker genes
marker_gene_plot_FAMB +
marker_gene_plot_MSP8 +
marker_gene_plot_MSP1 +
marker_gene_plot_CDPK5 +
marker_gene_plot_AP2G +
marker_gene_plot_CCP2 +
marker_gene_plot_MG1 +
marker_gene_plot_ORC1 +
marker_gene_plot_MCM4 +
  ## mutant genes starts  
#marker_gene_plot_gd1 +
#marker_gene_plot_md1 +
#marker_gene_plot_md2 +
#marker_gene_plot_md3 +
#marker_gene_plot_md4 + 
#marker_gene_plot_md5 +
#marker_gene_plot_fd1 +
#marker_gene_plot_fd2 +
#marker_gene_plot_fd3 +
#marker_gene_plot_fd4 + 
plot_layout(ncol = 6, 
            widths = c(1, 1, 1, 1, 1 ,1),
            heights = c(2, 1, 1, 1),
            design = layout
            )

Figure_publication

save

ggsave("../images_to_export/Figure_S2.png", plot = Figure_publication, device = "png", path = NULL, scale = 1, width = 21, height = 29.7, units = "cm", dpi = 300, limitsize = TRUE)

Appendix

Session Info

R version 4.0.3 (2020-10-10)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Catalina 10.15.7

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib

locale:
[1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8

attached base packages:
 [1] stats4    parallel  grid      stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] colourvalues_0.3.7          readxl_1.3.1                destiny_3.2.0               circlize_0.4.12            
 [5] gganimate_1.0.7             shiny_1.5.0                 monocle3_0.2.3.0            SingleCellExperiment_1.10.1
 [9] SummarizedExperiment_1.18.2 DelayedArray_0.14.1         matrixStats_0.57.0          GenomicRanges_1.40.0       
[13] GenomeInfoDb_1.24.2         IRanges_2.22.2              S4Vectors_0.26.1            Biobase_2.48.0             
[17] BiocGenerics_0.34.0         Nebulosa_1.2.0              reshape2_1.4.4              Hmisc_4.4-1                
[21] Formula_1.2-4               survival_3.2-7              lattice_0.20-41             gridExtra_2.3              
[25] dplyr_1.0.2                 patchwork_1.0.1             ggplot2bdc_0.3.2            cowplot_1.1.0              
[29] ggpubr_0.4.0                ggplot2_3.3.2               viridis_0.5.1               viridisLite_0.3.0          
[33] Seurat_3.2.2                colorspace_1.4-1           

loaded via a namespace (and not attached):
  [1] ggthemes_4.2.4            coda_0.19-4               tidyr_1.1.2               knitr_1.30               
  [5] irlba_2.3.3               data.table_1.13.2         rpart_4.1-15              RCurl_1.98-1.2           
  [9] generics_0.0.2            callr_3.5.1               leidenbase_0.1.2          usethis_1.6.3            
 [13] RANN_2.6.1                proxy_0.4-24              future_1.19.1             spatstat.data_1.4-3      
 [17] httpuv_1.5.4              assertthat_0.2.1          gifski_0.8.6              xfun_0.18                
 [21] hms_0.5.3                 evaluate_0.14             promises_1.1.1            DEoptimR_1.0-8           
 [25] fansi_0.4.1               progress_1.2.2            DBI_1.1.0                 igraph_1.2.6             
 [29] htmlwidgets_1.5.2         spdep_1.1-5               purrr_0.3.4               ellipsis_0.3.1           
 [33] RSpectra_0.16-0           crosstalk_1.1.0.1         ks_1.12.0                 backports_1.1.10         
 [37] deldir_0.1-29             vctrs_0.3.4               TTR_0.24.2                remotes_2.2.0            
 [41] ROCR_1.0-11               abind_1.4-5               RcppEigen_0.3.3.7.0       withr_2.3.0              
 [45] grr_0.9.5                 robustbase_0.93-7         checkmate_2.0.0           vcd_1.4-8                
 [49] sctransform_0.3.1         xts_0.12.1                prettyunits_1.1.1         mclust_5.4.7             
 [53] goftest_1.2-2             cluster_2.1.0             lazyeval_0.2.2            laeken_0.5.1             
 [57] crayon_1.3.4              units_0.6-7               slam_0.1-47               pkgconfig_2.0.3          
 [61] labeling_0.4.2            tweenr_1.0.1              nlme_3.1-149              pkgload_1.1.0            
 [65] nnet_7.3-14               devtools_2.3.2            rlang_0.4.8               globals_0.13.1           
 [69] lifecycle_0.2.0           miniUI_0.1.1.1            rsvd_1.0.3                cellranger_1.1.0         
 [73] rprojroot_1.3-2           polyclip_1.10-0           RcppHNSW_0.3.0            lmtest_0.9-38            
 [77] Matrix_1.2-18             raster_3.3-13             carData_3.0-4             Matrix.utils_0.9.8       
 [81] boot_1.3-25               zoo_1.8-8                 base64enc_0.1-3           ggridges_0.5.2           
 [85] GlobalOptions_0.1.2       processx_3.4.4            pheatmap_1.0.12           png_0.1-7                
 [89] bitops_1.0-6              KernSmooth_2.23-17        DelayedMatrixStats_1.10.1 classInt_0.4-3           
 [93] shape_1.4.5               stringr_1.4.0             jpeg_0.1-8.1              rstatix_0.6.0            
 [97] ggsignif_0.6.0            scales_1.1.1              memoise_1.1.0             magrittr_2.0.1           
[101] plyr_1.8.6                hexbin_1.28.1             ica_1.0-2                 gdata_2.18.0             
[105] zlibbioc_1.34.0           compiler_4.0.3            RColorBrewer_1.1-2        pcaMethods_1.80.0        
[109] fitdistrplus_1.1-1        cli_2.1.0                 LearnBayes_2.15.1         XVector_0.28.0           
[113] listenv_0.8.0             pbapply_1.4-3             ps_1.4.0                  htmlTable_2.1.0          
[117] ggplot.multistats_1.0.0   MASS_7.3-53               mgcv_1.8-33               tidyselect_1.1.0         
[121] stringi_1.5.3             forcats_0.5.0             yaml_2.2.1                latticeExtra_0.6-29      
[125] ggrepel_0.8.2             pbmcapply_1.5.0           tools_4.0.3               future.apply_1.6.0       
[129] rio_0.5.16                rstudioapi_0.11           foreign_0.8-80            smoother_1.1             
[133] scatterplot3d_0.3-41      farver_2.0.3              Rtsne_0.15                digest_0.6.27            
[137] BiocManager_1.30.10       Rcpp_1.0.6                car_3.0-10                broom_0.7.2              
[141] later_1.1.0.1             RcppAnnoy_0.0.16          httr_1.4.2                sf_0.9-6                 
[145] fs_1.5.0                  tensor_1.5                ranger_0.12.1             reticulate_1.18          
[149] splines_4.0.3             uwot_0.1.8                expm_0.999-5              spatstat.utils_1.17-0    
[153] sp_1.4-4                  spData_0.3.8              plotly_4.9.2.1            sessioninfo_1.1.1        
[157] xtable_1.8-4              jsonlite_1.7.1            spatstat_1.64-1           testthat_2.3.2           
[161] R6_2.5.0                  gmodels_2.18.1            pillar_1.4.6              htmltools_0.5.1.1        
[165] mime_0.9                  glue_1.4.2                fastmap_1.0.1             VIM_6.1.0                
[169] class_7.3-17              codetools_0.2-16          utf8_1.1.4                pkgbuild_1.1.0           
[173] mvtnorm_1.1-1             tibble_3.0.4              curl_4.3                  leiden_0.3.3             
[177] gtools_3.8.2              zip_2.1.1                 openxlsx_4.2.2            limma_3.44.3             
[181] rmarkdown_2.5             desc_1.2.0                munsell_0.5.0             e1071_1.7-4              
[185] GenomeInfoDbData_1.2.3    haven_2.3.1               gtable_0.3.0             

Expression plots

Expression - raw - Viridis

## find a good ring marker, to see if there is a better one than the ones reported
#markers_ring <- FindMarkers(tenx.justwt.integrated, ident.1 = c("4", "5", "16", "11", "7", "3", "9", "0", "22"))
#head(markers_ring)

# PBANKA-1319500 - CCP2 - female - used in 820 line
# PBANKA-0416100 - MG1 - dynenin heavy chain - male - used in 820 line
# PBANKA-1437500 - AP2G - commitment
# PBANKA-0831000 - MSP1 - late asexual
# PBANKA-1102200 - MSP8 - early asexual (from Bozdech paper)
# PBANKA-0711900 - HSP70 - promoter used for GFP and RFP expression in the mutants
# PBANKA-1400400 - FAMB - ring marker - discovered by looking for marker genes in data
# PBANKA-0722600 - Fam-b2 - ring marker - https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5113031/ 


marker_gene_plot_CCP2 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1319500", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste(italic(ccp2), "(Female)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))
Error in italic(ccp2) : could not find function "italic"

Expression - raw - purple


marker_gene_ramp <- colorRampPalette(c("#D3D3D3", "#1D1564"))(50)

marker_gene_plot_CCP2 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1319500", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("CCP2 (Female)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MG1 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0416100", coord.fixed = TRUE, 
                                    #min.cutoff = "q1", 
                                    dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("MG1 (Male)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_AP2G <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1437500", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("AP2G (Commitment)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MSP1 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0831000", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("MSP1 (Schizont)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MSP8 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1102200", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("MSP8 (Asexual)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_SBP1 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1101300", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("SBP1 (Ring)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_FAMB <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0722600", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("Fam-b2 (Ring)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_HSP70 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0711900", coord.fixed = TRUE, 
                                      #min.cutoff = "q1", 
                                      dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("(HSP70; Reporter)","\n", "PBANKA_0711900")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
## plot
## cowplot method
marker_gene_plot_all <- plot_grid(marker_gene_plot_FAMB, marker_gene_plot_MSP8, marker_gene_plot_MSP1, marker_gene_plot_AP2G, marker_gene_plot_CCP2, marker_gene_plot_MG1, marker_gene_plot_HSP70, nrow=3)
font family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font database
marker_gene_plot_all

Expression - data - purple

# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-0102400         GCSKO-2  MD3 
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-1435200        GCSKO-20  FD4 
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-0413400    GCSKO-10_820  MD5
# PBANKA-0828000         GCSKO-3  GD1
# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-1144800        GCSKO-28  FD5


marker_gene_plot_17 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1418100", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd3")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_2 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0102400", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md3")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_19 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0716500", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md4")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_20 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1435200", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd4")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_13 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0902300", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd2")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_10 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0413400", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md5")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_3 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0828000", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("gd1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_oom <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1302700", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_29 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1447900", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md2")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_21 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1454800", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
##original label:
# labs(title = paste("(CCP2; Female)","\n", "PBANKA_1319500"))

## make composite plot
mutant_expression_composite <- wrap_plots(marker_gene_plot_17 , marker_gene_plot_2 , marker_gene_plot_19 , marker_gene_plot_20 , marker_gene_plot_13 , marker_gene_plot_10 , marker_gene_plot_3 , marker_gene_plot_oom , marker_gene_plot_29 , marker_gene_plot_21 , ncol = 4)
           
## print
mutant_expression_composite

Density Plots

Density - purple

# PBANKA-1319500 - CCP2 - female - used in 820 line
# PBANKA-0416100 - MG1 - dynenin heavy chain - male - used in 820 line
# PBANKA-1437500 - AP2G - commitment
# PBANKA-0831000 - MSP1 - late asexual
# PBANKA-1102200 - MSP8 - early asexual (from Bozdech paper)
# PBANKA-0711900 - HSP70 - promoter used for GFP and RFP expression in the mutants
# PBANKA-1400400 - FAMB - ring marker - discovered by looking for marker genes in data
# PBANKA-0722600 - Fam-b2 - ring marker - https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5113031/ 

markers_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0102400", "PBANKA-0716500", "PBANKA-0413400", "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

list_of_density_plots_mutant_genes <- plot_density(tenx.justwt.integrated, markers_list, joint = FALSE, combine = FALSE, dims = c(1,2), pal = "plasma", method = "ks")

## make composite plot
UMAP_composite_mutant_genes <- wrap_plots(list_of_density_plots_mutant_genes[[1]] + 
                                            coord_fixed() + 
                                            theme_void() + 
                                            labs(title = paste("gd1")) + 
                                            scale_colour_gradientn(colours=marker_gene_ramp) + 
                                            guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[2]] + 
                               coord_fixed() + theme_void() + 
                               labs(title = paste("md1")) + 
                               scale_colour_gradientn(colours=marker_gene_ramp) + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[3]] + coord_fixed() + theme_void() + labs(title = paste("md2")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[4]] + coord_fixed() + theme_void() + labs(title = paste("md3")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[5]] + coord_fixed() + theme_void() + 
  labs(title = paste("md4")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[6]] + coord_fixed() + theme_void() + labs(title = paste("md5")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[7]] + coord_fixed() + theme_void() + labs(title = paste("fd1")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[8]] + coord_fixed() + theme_void() + labs(title = paste("fd2")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[9]] + coord_fixed() + theme_void() + labs(title = paste("fd3")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[10]] + coord_fixed() + theme_void() + labs(title = paste("fd4")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             ncol = 4)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
UMAP_composite_mutant_genes

Density -viridis

# PBANKA-1319500 - CCP2 - female - used in 820 line
# PBANKA-0416100 - MG1 - dynenin heavy chain - male - used in 820 line
# PBANKA-1437500 - AP2G - commitment
# PBANKA-0831000 - MSP1 - late asexual
# PBANKA-1102200 - MSP8 - early asexual (from Bozdech paper)
# PBANKA-0711900 - HSP70 - promoter used for GFP and RFP expression in the mutants
# PBANKA-1400400 - FAMB - ring marker - discovered by looking for marker genes in data
# PBANKA-0722600 - Fam-b2 - ring marker - https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5113031/ 

markers_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0102400", "PBANKA-0716500", "PBANKA-0413400", "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

list_of_density_plots_mutant_genes <- plot_density(tenx.justwt.integrated, markers_list, joint = FALSE, combine = FALSE, dims = c(1,2), pal = "plasma", method = "ks")

## make composite plot
UMAP_composite_mutant_genes <- wrap_plots(list_of_density_plots_mutant_genes[[1]] + 
                                            coord_fixed() + 
                                            theme_void() + 
                                            labs(title = paste("gd1")) + 
                                            scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + 
                                            guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[2]] + 
                               coord_fixed() + theme_void() + 
                               labs(title = paste("md1")) + 
                               scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[3]] + coord_fixed() + theme_void() + labs(title = paste("md2")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[4]] + coord_fixed() + theme_void() + labs(title = paste("md3")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)) )+ guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[5]] + coord_fixed() + theme_void() + 
  labs(title = paste("md4")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[6]] + coord_fixed() + theme_void() + labs(title = paste("md5")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[7]] + coord_fixed() + theme_void() + labs(title = paste("fd1")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[8]] + coord_fixed() + theme_void() + labs(title = paste("fd2")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[9]] + coord_fixed() + theme_void() + labs(title = paste("fd3")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[10]] + coord_fixed() + theme_void() + labs(title = paste("fd4")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             ncol = 4)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
UMAP_composite_mutant_genes

Density - viridis

# PBANKA-0828000         GCSKO-3  GD1

# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-0102400         GCSKO-2  MD3 
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-0413400    GCSKO-10_820  MD5

# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-1435200        GCSKO-20  FD4 

markers_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0102400", "PBANKA-0716500", "PBANKA-0413400", "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

list_of_density_plots_mutant_genes <- plot_density(tenx.justwt.integrated, markers_list, joint = FALSE, combine = FALSE, dims = c(1,2), pal = "plasma", method = "ks")

## make composite plot
UMAP_composite_mutant_genes <- wrap_plots(list_of_density_plots_mutant_genes[[1]] + 
                                            coord_fixed() + 
                                            theme_void() + 
                                            labs(title = paste("gd1")) + 
                                            scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + 
                                            guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[2]] + 
                               coord_fixed() + theme_void() + 
                               labs(title = paste("md1")) + 
                               scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[3]] + coord_fixed() + theme_void() + labs(title = paste("md2")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[4]] + coord_fixed() + theme_void() + labs(title = paste("md3")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)) )+ guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[5]] + coord_fixed() + theme_void() + 
  labs(title = paste("md4")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[6]] + coord_fixed() + theme_void() + labs(title = paste("md5")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[7]] + coord_fixed() + theme_void() + labs(title = paste("fd1")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[8]] + coord_fixed() + theme_void() + labs(title = paste("fd2")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[9]] + coord_fixed() + theme_void() + labs(title = paste("fd3")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[10]] + coord_fixed() + theme_void() + labs(title = paste("fd4")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             ncol = 4)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
UMAP_composite_mutant_genes

# PBANKA-0828000         GCSKO-3  GD1

# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-0102400         GCSKO-2  MD3 
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-0413400    GCSKO-10_820  MD5

# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-1435200        GCSKO-20  FD4 

markers_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0102400", "PBANKA-0716500", "PBANKA-0413400", "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

list_of_density_plots_mutant_genes <- plot_density(tenx.justwt.integrated, markers_list, joint = FALSE, combine = FALSE, dims = c(1,2), pal = "plasma", method = "wkde", slot = 'data')

## make composite plot
UMAP_composite_mutant_genes <- wrap_plots(list_of_density_plots_mutant_genes[[1]] + 
                                            coord_fixed() + 
                                            theme_void() + 
                                            labs(title = paste("gd1")) + 
                                            scale_color_continuous_sequential(palette = "Purples 2") + 
                                            guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[2]] + 
                               coord_fixed() + theme_void() + 
                               labs(title = paste("md1")) + 
                               scale_color_continuous_sequential(palette = "Purples 2") + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[3]] + 
                               coord_fixed() + 
                               theme_void() + 
                               labs(title = paste("md2")) + scale_color_continuous_sequential(palette = "Purples 2") + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[4]] + coord_fixed() + theme_void() + labs(title = paste("md3")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[5]] + coord_fixed() + theme_void() + 
  labs(title = paste("md4")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[6]] + coord_fixed() + theme_void() + labs(title = paste("md5")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[7]] + coord_fixed() + theme_void() + labs(title = paste("fd1")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[8]] + coord_fixed() + theme_void() + labs(title = paste("fd2")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[9]] + coord_fixed() + theme_void() + labs(title = paste("fd3")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[10]] + coord_fixed() + theme_void() + labs(title = paste("fd4")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             ncol = 4)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
## old colour scale: scale_colour_gradientn(colours=marker_gene_ramp )

UMAP_composite_mutant_genes

LS0tCnN1YnRpdGxlOiAnR2FtZXRvY3l0ZSBEZXZlbG9wbWVudCBpbiA8aT5QbGFzbW9kaXVtIGJlcmdoZWk8L2k+Jwp0aXRsZTogfAogICFbXSguLi9HQ1NLT19sb2dvLmpwZyl7d2lkdGg9MzAwcHh9ICAKICBNZXJnaW5nIFNtYXJ0LXNlcTIgYW5kIDEwWCBEYXRhc2V0cyAtIHdpbGQtdHlwZSBvbmx5CmF1dGhvcjogIltBbmRyZXcgUnVzc2VsbF0oaHR0cHM6Ly9hamNydXNzZWxsLndpeHNpdGUuY29tL215c2l0ZS9hYm91dCkiCmluc3RpdHV0ZTogV2VsbGNvbWUgU2FuZ2VyIEluc3RpdHV0ZQpkYXRlOiAnYHIgZm9ybWF0KFN5cy5EYXRlKCksICIlQiAlZCwgJVkiKWAnCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAzCiAgICAjdG9jX2Zsb2F0OiB5ZXMKICAgIGRmX3ByaW50OiBwYWdlZAotLS0KKioqCiMgMS4gSW50cm9kdWN0aW9uIGFuZCBBaW1zIHsudGFic2V0fQoKV2UgaGF2ZSBxdWFsaXR5LWNvbnRyb2xsZWQgdGhlIDEwWCBkYXRhIGFuZCB0aGUgU1MyIGRhdGEgYW5kIG5vdyBhcmUgbGVmdCB3aXRoIHRoZSBmb2xsb3dpbmcgb2JqZWN0czoKCjEwWCA1SyBkYXRhIC0gcGJfc2V4X2ZpbHRlcmVkCgoxMFggMzBLIGRhdGEgLSBwYl8zMGtfc2V4X2ZpbHRlcmVkIAoKU1MyIG11dGFudCBkYXRhIC0gc3MyX211dGFudHNfZmluYWwKCiMgMi4gUmVhZCBpbiB0aGUgZGF0YSAgey50YWJzZXR9CgojIyMgTG9hZC9JbnN0YWxsIHRoZSBSZXF1aXJlZCBQYWNrYWdlcwoKYGBge3IgbG9hZCBwYWNrYWdlcywgZWNobyA9IEZBTFNFfQojIyBDUkFOIHBhY2thZ2VzCgojIyBQYXRod29yayBpcyBuZWVkZWQgdG8gc3RpY2ggcGxvdHMgdG9nZXRoZXIgdXNpbmcgJysnCmlmKHJlcXVpcmUoInBhdGNod29yayIsIHF1aWV0bHkgPSBUUlVFKSl7CiAgICBwcmludCgicGF0Y2h3b3JrIGlzIGxvYWRlZCBjb3JyZWN0bHkiKQp9IGVsc2UgewogICAgcHJpbnQoInRyeWluZyB0byBpbnN0YWxsIHBhdGNod29yayIpCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJwYXRjaHdvcmsiKQogICAgaWYocmVxdWlyZShwYXRjaHdvcmspKXsKICAgICAgICBwcmludCgicGF0Y2h3b3JrIGluc3RhbGxlZCBhbmQgbG9hZGVkIikKICAgIH0gZWxzZSB7CiAgICAgICAgc3RvcCgiY291bGQgbm90IGluc3RhbGwgcGF0Y2h3b3JrIikKICAgIH0KfQoKIyMgdmlyaWRpcyBhbGxvd3MgZGlmZmVyZW50IGNvbG91cnMgdG8gYmUgYWRkZWQgdG8gcGxvdHMKaWYocmVxdWlyZSgidmlyaWRpcyIsIHF1aWV0bHkgPSBUUlVFKSl7CiAgICBwcmludCgidmlyaWRpcyBpcyBsb2FkZWQgY29ycmVjdGx5IikKfSBlbHNlIHsKICAgIHByaW50KCJ0cnlpbmcgdG8gaW5zdGFsbCB2aXJpZGlzIikKICAgIGluc3RhbGwucGFja2FnZXMoInZpcmlkaXMiKQogICAgaWYocmVxdWlyZSh2aXJpZGlzKSl7CiAgICAgICAgcHJpbnQoInZpcmlkaXMgaW5zdGFsbGVkIGFuZCBsb2FkZWQiKQogICAgfSBlbHNlIHsKICAgICAgICBzdG9wKCJjb3VsZCBub3QgaW5zdGFsbCB2aXJpZGlzIikKICAgIH0KfQoKIyMgU2V1cmF0IGlzIG5lZWRlZCBmb3IgbW9zdCBvZiB0aGlzIHNjcmlwdAppZihyZXF1aXJlKCJTZXVyYXQiLCBxdWlldGx5ID0gVFJVRSkpewogICAgcHJpbnQoIlNldXJhdCBpcyBsb2FkZWQgY29ycmVjdGx5IikKfSBlbHNlIHsKICAgIHByaW50KCJ0cnlpbmcgdG8gaW5zdGFsbCBTZXVyYXQiKQogICAgaW5zdGFsbC5wYWNrYWdlcygiU2V1cmF0IikKICAgIGlmKHJlcXVpcmUoU2V1cmF0KSl7CiAgICAgICAgcHJpbnQoIlNldXJhdCBpbnN0YWxsZWQgYW5kIGxvYWRlZCIpCiAgICB9IGVsc2UgewogICAgICAgIHN0b3AoImNvdWxkIG5vdCBpbnN0YWxsIFNldXJhdCIpCiAgICB9Cn0KCiMjIGNvd3Bsb3QgaXMgbmVlZGVkIGZvciBwbG90cyBpbiB0aGlzIHNjcmlwdAppZihyZXF1aXJlKCJjb3dwbG90IikpewogICAgcHJpbnQoImNvd3Bsb3QgaXMgbG9hZGVkIGNvcnJlY3RseSIpCn0gZWxzZSB7CiAgICBwcmludCgidHJ5aW5nIHRvIGluc3RhbGwgY293cGxvdCIpCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJjb3dwbG90IikKICAgIGlmKHJlcXVpcmUoY293cGxvdCkpewogICAgICAgIHByaW50KCJjb3dwbG90IGluc3RhbGxlZCBhbmQgbG9hZGVkIikKICAgIH0gZWxzZSB7CiAgICAgICAgc3RvcCgiY291bGQgbm90IGluc3RhbGwgY293cGxvdCIpCiAgICB9Cn0KCiMjIGdyaWRFeHRyYSBpcyBuZWVkZWQgZm9yIGdyaWQgZ3JhcGhpY3MgdG8gcGxvdCBtdWx0aXBsZSBwbG90cyBpbiB0aGUgc2FtZSB2aWV3CmlmKHJlcXVpcmUoImdyaWRFeHRyYSIpKXsKICAgIHByaW50KCJncmlkRXh0cmEgaXMgbG9hZGVkIGNvcnJlY3RseSIpCn0gZWxzZSB7CiAgICBwcmludCgidHJ5aW5nIHRvIGluc3RhbGwgZ3JpZEV4dHJhIikKICAgIGluc3RhbGwucGFja2FnZXMoImdyaWRFeHRyYSIpCiAgICBpZihyZXF1aXJlKGdyaWRFeHRyYSkpewogICAgICAgIHByaW50KCJncmlkRXh0cmEgaW5zdGFsbGVkIGFuZCBsb2FkZWQiKQogICAgfSBlbHNlIHsKICAgICAgICBzdG9wKCJjb3VsZCBub3QgaW5zdGFsbCBncmlkRXh0cmEiKQogICAgfQp9CgojIyBncmlkIGlzIG5lZWRlZCBmb3IgZ3JpZC5hcnJhbmdlIGZ1bmN0aW9uIHRvIGNoYW5nZSBzaXplIG9mIHRpdGxlCmlmKHJlcXVpcmUoImdyaWQiKSl7CiAgICBwcmludCgiZ3JpZCBpcyBsb2FkZWQgY29ycmVjdGx5IikKfSBlbHNlIHsKICAgIHByaW50KCJ0cnlpbmcgdG8gaW5zdGFsbCBncmlkIikKICAgIGluc3RhbGwucGFja2FnZXMoImdyaWQiKQogICAgaWYocmVxdWlyZShncmlkKSl7CiAgICAgICAgcHJpbnQoImdyaWQgaW5zdGFsbGVkIGFuZCBsb2FkZWQiKQogICAgfSBlbHNlIHsKICAgICAgICBzdG9wKCJjb3VsZCBub3QgaW5zdGFsbCBncmlkIikKICAgIH0KfQoKIyNmb3IgZG9pbmcgYnVsayBjb3JyZWxhdGlvbiBjYWxjdWxhdGlvbnMKaWYocmVxdWlyZSgiSG1pc2MiKSl7CiAgICBwcmludCgiSG1pc2MgaXMgbG9hZGVkIGNvcnJlY3RseSIpCn0gZWxzZSB7CiAgICBwcmludCgidHJ5aW5nIHRvIGluc3RhbGwgSG1pc2MiKQogICAgaW5zdGFsbC5wYWNrYWdlcygiSG1pc2MiKQogICAgaWYocmVxdWlyZShIbWlzYykpewogICAgICAgIHByaW50KCJIbWlzYyBpbnN0YWxsZWQgYW5kIGxvYWRlZCIpCiAgICB9IGVsc2UgewogICAgICAgIHN0b3AoImNvdWxkIG5vdCBpbnN0YWxsIEhtaXNjIikKICAgIH0KfQoKIyMgcmVzaGFwZTIgdG8gbWVsdCBkYXRhZnJhbWVzIGZvciBwbG90dGluZzoKaWYocmVxdWlyZSgicmVzaGFwZTIiKSl7CiAgICBwcmludCgicmVzaGFwZTIgaXMgbG9hZGVkIGNvcnJlY3RseSIpCn0gZWxzZSB7CiAgICBwcmludCgidHJ5aW5nIHRvIGluc3RhbGwgcmVzaGFwZTIiKQogICAgaW5zdGFsbC5wYWNrYWdlcygicmVzaGFwZTIiKQogICAgaWYocmVxdWlyZShyZXNoYXBlMikpewogICAgICAgIHByaW50KCJyZXNoYXBlMiBpbnN0YWxsZWQgYW5kIGxvYWRlZCIpCiAgICB9IGVsc2UgewogICAgICAgIHN0b3AoImNvdWxkIG5vdCBpbnN0YWxsIHJlc2hhcGUyIikKICAgIH0KfQoKIyMgdG8gd29yayB3aXRoIGRhdGEgZnJhbWVzOgppZihyZXF1aXJlKCJkcGx5ciIpKXsKICAgIHByaW50KCJkcGx5ciBpcyBsb2FkZWQgY29ycmVjdGx5IikKfSBlbHNlIHsKICAgIHByaW50KCJ0cnlpbmcgdG8gaW5zdGFsbCBkcGx5ciIpCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpCiAgICBpZihyZXF1aXJlKGRwbHlyKSl7CiAgICAgICAgcHJpbnQoImRwbHlyIGluc3RhbGxlZCBhbmQgbG9hZGVkIikKICAgIH0gZWxzZSB7CiAgICAgICAgc3RvcCgiY291bGQgbm90IGluc3RhbGwgZHBseXIiKQogICAgfQp9CgojIyBub24tQ1JBTiBwYWNrYWdlcwoKIyMgdG8gbWFrZSBkZW5zaXR5IHBsb3RzIHNob3dpbmcgZ2VuZSBleHByZXNzaW9uCmlmKHJlcXVpcmUoIk5lYnVsb3NhIikpewogICAgcHJpbnQoIk5lYnVsb3NhIGlzIGxvYWRlZCBjb3JyZWN0bHkiKQp9IGVsc2UgewogICAgcHJpbnQoInRyeWluZyB0byBpbnN0YWxsIE5lYnVsb3NhIikKICAgIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigicG93ZWxsZ2Vub21pY3NsYWIvTmVidWxvc2EiKQogICAgaWYocmVxdWlyZShOZWJ1bG9zYSkpewogICAgICAgIHByaW50KCJOZWJ1bG9zYSBpbnN0YWxsZWQgYW5kIGxvYWRlZCIpCiAgICB9IGVsc2UgewogICAgICAgIHN0b3AoImNvdWxkIG5vdCBpbnN0YWxsIE5lYnVsb3NhIikKICAgIH0KfQoKIyMgbW9ub2NsZTMgdG8gY2FsY3VsYXRlIHBzZXVkb3RpbWU6CmlmKHJlcXVpcmUoIm1vbm9jbGUzIikpewogICAgcHJpbnQoIm1vbm9jbGUzIGlzIGxvYWRlZCBjb3JyZWN0bHkiKQp9IGVsc2UgewogICAgcHJpbnQoIlBsZWFzZSBpbnN0YWxsIG1vbm9jbGUzIChodHRwczovL2NvbGUtdHJhcG5lbGwtbGFiLmdpdGh1Yi5pby9tb25vY2xlMy9kb2NzL2luc3RhbGxhdGlvbi8pIikKfQoKIyMgc2V0IHRoZSBzZWVkIGZvciBib3RoIHRoZSBtaXh0dXJlIG1vZGVscyBhbmQgYWxzbyBmb3IgdGhlIHNhbXBsZSBmdW5jdGlvbiBsYXRlciBvbjoKc2V0LnNlZWQoLTkyNDk3KQpgYGAKCiMjIyBSZWFkIGluIHRoZSBEYXRhCgpzY3JlZW4gaGl0cwpgYGB7cn0KIyMgRURJVCAtIGNoYW5nZSB0aGlzIHRvIHRoZSBleGNlbCB0YWJsZSBvbmNlIHdlIGhhdmUgaXQgZmluYWxpemVkIGZvciB0aGUgc2NyZWVuCnNjcmVlbl9oaXRzIDwtIGMoIlBCQU5LQS0wNTE2MzAwIiwKIlBCQU5LQS0xMjE3NzAwIiwKIlBCQU5LQS0wNDA5MTAwIiwKIlBCQU5LQS0xMDM0MzAwIiwKIlBCQU5LQS0xNDM3NTAwIiwKIlBCQU5LQS0wODI3NTAwIiwKIlBCQU5LQS0wODI0MzAwIiwKIlBCQU5LQS0xNDI2OTAwIiwKIlBCQU5LQS0wMTA1MzAwIiwKIlBCQU5LQS0wOTIxMTAwIiwKIlBCQU5LQS0xMDAyNDAwIiwKIlBCQU5LQS0wODI5NDAwIiwKIlBCQU5LQS0xMzQ3MjAwIiwKIlBCQU5LQS0wODI4MDAwIiwKIlBCQU5LQS0wOTAyMzAwIiwKIlBCQU5LQS0xNDE4MTAwIiwKIlBCQU5LQS0xNDM1MjAwIiwKIlBCQU5LQS0xNDU0ODAwIiwKIlBCQU5LQS0wNzEyMzAwIiwKIlBCQU5LQS0wNDEwNTAwIiwKIlBCQU5LQS0xMTQ0ODAwIiwKIlBCQU5LQS0xMjMxNjAwIiwKIlBCQU5LQS0wNTAzMjAwIiwKIlBCQU5LQS0wMzA4OTAwIiwKIlBCQU5LQS0xMjE0NzAwIiwKIlBCQU5LQS0wNzA5OTAwIiwKIlBCQU5LQS0wMzExOTAwIiwKIlBCQU5LQS0wNzE2NTAwIiwKIlBCQU5LQS0xNDQ3OTAwIiwKIlBCQU5LQS0wMTAyMjAwIiwKIlBCQU5LQS0wNzEzNTAwIiwKIlBCQU5LQS0wMTAyNDAwIiwKIlBCQU5LQS0xMzAyNzAwIiwKIlBCQU5LQS0xMjM1OTAwIiwKIlBCQU5LQS0wNDAxMTAwIiwKIlBCQU5LQS0wNDEzNDAwIiwKIlBCQU5LQS0xMTI2OTAwIiwKIlBCQU5LQS0xNDI1OTAwIiwKIlBCQU5LQS0wNDE4MzAwIiwKIlBCQU5LQS0xNDY0NjAwIiwKIlBCQU5LQS0wODA2MDAwIikKYGBgCgpSZWFkIGluIGdlbmUgYW5ub3RhdGlvbnMKYGBge3J9CmdlbmVfYW5ub3RhdGlvbnMgPC0gcmVhZC50YWJsZSgiLi4vZGF0YS9SZWZlcmVuY2UvR2VuZXNCeVRheG9uX1N1bW1hcnkuY3N2IiwgaGVhZGVyID0gVFJVRSwgc2VwID0gIiwiLCBzdHJpbmdzQXNGYWN0b3JzID0gVFJVRSkKZGltKGdlbmVfYW5ub3RhdGlvbnMpCgojIyBjb252ZXJ0IF8gdG8gLQpnZW5lX2Fubm90YXRpb25zJEdlbmUuSUQgPC0gZ3N1YigiXyIsICItIiwgZ2VuZV9hbm5vdGF0aW9ucyRHZW5lLklEKQpgYGAKCmxvYWQgaW4gZGF0YXNldHMKYGBge3J9CiMjIGxvYWQgdGhlIDEwWCBkYXRhc2V0CnBiX3NleF9maWx0ZXJlZCA8LSByZWFkUkRTKCIuLi9kYXRhX3RvX2V4cG9ydC9wYl9zZXhfZmlsdGVyZWQuUkRTIikKIyMgbG9hZCB0aGUgU1MyIGRhdGFzZXQKc3MyX211dGFudHNfZmluYWwgPC0gcmVhZFJEUygiLi4vZGF0YV90b19leHBvcnQvc3MyX211dGFudHNfZmluYWwuUkRTIikKCiMjIGluc3BlY3QKcGFzdGUoIjEweCBkYXRhc2V0IikKcGJfc2V4X2ZpbHRlcmVkCnBhc3RlKCJTbWFydC1zZXEyIGRhdGFzZXQiKQpzczJfbXV0YW50c19maW5hbApwYXN0ZSgiVGhlIGNvbXBvc2l0aW9uIG9mIHRoZSBTbWFydC1zZXEyIGRhdGFzZXQgaXM6IikKdGFibGUoc3MyX211dGFudHNfZmluYWxAbWV0YS5kYXRhJGdlbm90eXBlKQpgYGAKCiMgMy4gTWVyZ2luZyB0aGUgU21hcnQtc2VxMiBhbmQgMTBYIERhdGEgey50YWJzZXR9CgojIyMgUHJlcGFyZSBkYXRhCgpgYGB7ciBpbnRlZ3JhdGlvbiAxMHggc2V0dXB9CiMjIGV4dHJhY3QgMTB4IGRhdGEKdGVueF81a19jb3VudHMgPC0gYXMubWF0cml4KHBiX3NleF9maWx0ZXJlZEBhc3NheXMkUk5BQGNvdW50cykKdGVueF81a19waGVubyA8LSBwYl9zZXhfZmlsdGVyZWRAbWV0YS5kYXRhCgojIyBDcmVhdGUgZnJlc2ggb2JqZWN0CnRlbnhfNWtfY291bnRzX3RvX2ludGVncmF0ZSA8LSBDcmVhdGVTZXVyYXRPYmplY3QoY291bnRzID0gdGVueF81a19jb3VudHMsIG1ldGEuZGF0YSA9IHRlbnhfNWtfcGhlbm8sIG1pbi5jZWxscyA9IDAsIG1pbi5mZWF0dXJlcyA9IDAsIHByb2plY3QgPSAiR0NTS08iKQoKIyMgYWRkIGV4cGVyaW1lbnQgbWV0YSBkYXRhCnRlbnhfNWtfY291bnRzX3RvX2ludGVncmF0ZUBtZXRhLmRhdGEkZXhwZXJpbWVudCA8LSAidGVueF81ayIKCiMjIGluc3BlY3QKdGVueF81a19jb3VudHNfdG9faW50ZWdyYXRlCmBgYAoKV2UgbmVlZCB0byBtYWtlIHN1cmUgdGhlIG11dGFudCBkYXRhIGlzIGNvbXBhdGlibGUgd2l0aCB0aGUgMTBYIGRhdGEuIHRoZSAxMFggZGF0YSBoYXMgZmV3ZXIgZ2VuZXMgcmVwcmVzZW50ZWQgc28gd2UgbmVlZCB0byBmaW5kIHRoZSBpbnRlcnNlY3Qgb2YgdGhlIHR3byBiZWZvcmUgaW50ZWdyYXRpb24uCmBgYHtyIGludGVncmF0aW9uIHNzMiBzZXR1cH0KIyMgZXh0cmFjdCBTUzIgZGF0YSAKbXV0YW50X2NvdW50c19mb3JfaW50ZWdyYXRpb24gPC0gYXMubWF0cml4KHNzMl9tdXRhbnRzX2ZpbmFsQGFzc2F5cyRSTkFAY291bnRzKQptdXRhbnRfcGhlbm9fZm9yX2ludGVncmF0aW9uIDwtIHNzMl9tdXRhbnRzX2ZpbmFsQG1ldGEuZGF0YQoKIyMgY2hhbmdlIGNvdW50cyBzbyB0aGUgOnJSTkEgYW5kIDp0Uk5BIGFyZSBub3QgdGhlcmU6CnJvd25hbWVzKG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uKSA8LSBnc3ViKCI6bmNSTkEiLCAiIiwgZ3N1YigiOnJSTkEiLCAiIiwgZ3N1YigiOnRSTkEiLCAiIiwgcm93bmFtZXMobXV0YW50X2NvdW50c19mb3JfaW50ZWdyYXRpb24pKSkpCgojIyBjaGFuZ2UgdGhlIGdlbmUgbmFtZXMgc28gdGhhdCB0aGV5IGFyZSAtIHJhdGhlciB0aGFuIF86CnJvd25hbWVzKG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uKSA8LSBnc3ViKCJfIiwgIi0iLCByb3duYW1lcyhtdXRhbnRfY291bnRzX2Zvcl9pbnRlZ3JhdGlvbikpCgojIyBjYWxjdWxhdGUgaG93IG1hbnkgb2YgdGhlIGdlbmVzIG92ZXJsYXAgLSAxMHggZG9lcyBzdGFydCBvdXQgd2l0aCA1MDk4IHZzIDUyNDUKZ2VuZXNfaW5fdGVueF9kYXRhc2V0IDwtIGludGVyc2VjdChyb3duYW1lcyh0ZW54XzVrX2NvdW50cyksIHJvd25hbWVzKG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uKSkKIyMgcHJpbnQgbnVtYmVyIG9mIGdlbmVzIHRoYXQgb3ZlcmxhcApkaW0obXV0YW50X2NvdW50c19mb3JfaW50ZWdyYXRpb24pCiMjIHN1YnNldCB0aGUgbXV0YW50IGNvdW50cyB0byBjb250YWluIG9ubHkgMTB4IGdlbmVzCm11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uIDwtIG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uW3doaWNoKHJvd25hbWVzKG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uKSAlaW4lIGdlbmVzX2luX3RlbnhfZGF0YXNldCksIF0KIyMgcHJpbnQgcmVzdWx0IG9mIGdlbmVzIHRoYXQgb3ZlcmxhcApkaW0obXV0YW50X2NvdW50c19mb3JfaW50ZWdyYXRpb24pCgojIyBtYWtlIFNldXJhdCBvYmplY3Q6CkdDU0tPX211dGFudHMgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGNvdW50cyA9IG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uLCBtZXRhLmRhdGEgPSBtdXRhbnRfcGhlbm9fZm9yX2ludGVncmF0aW9uLCBtaW4uY2VsbHMgPSAwLCBtaW4uZmVhdHVyZXMgPSAwLCBwcm9qZWN0ID0gIkdDU0tPIikKCiMjIGFkZCBleHBlcmltZW50IG1ldGEgZGF0YQpHQ1NLT19tdXRhbnRzQG1ldGEuZGF0YSRleHBlcmltZW50IDwtICJtdXRhbnRzIgoKIyMgaW5zcGVjdApHQ1NLT19tdXRhbnRzCmBgYAoKYGBge3J9CiMjIGRvdWJsZSBjaGVjayB0aGF0IHRoaXMgaXMgdGhlIHNhbWUgbnVtYmVyIG9mIGdlbmVzCiMjIHN1YnNldCBjb3VudHMgc28gdGhhdCBvbmx5IGdlbmVzIHJlcHJlc2VudGVkIGluIHRoZSBvdGhlciB0d28gb2JqZWN0cyBhcmUgdGhlcmU6Cmxlbmd0aChpbnRlcnNlY3Qocm93bmFtZXModGVueF81a19jb3VudHMpLCByb3duYW1lcyhtdXRhbnRfY291bnRzX2Zvcl9pbnRlZ3JhdGlvbikpKQpgYGAKCklNUE9SVEFOVCAtIHRoaXMgbmV4dCBzdGVwIGlzIGRpZmZlcmVudCB0byBHQ1NLT19tZXJnZSBhcyBpdCBzdWJzZXRzIHRoZSBzbWFydC1zZXEyIGRhdGEgaW50byB3aWxkLXR5cGUgb25seS4gCmBgYHtyfQojIyBzdWJzZXQgd3Qgb24gc3MyIGRhdGE6CnNzMl93dF9jZWxscyA8LSByb3duYW1lcyhHQ1NLT19tdXRhbnRzQG1ldGEuZGF0YVtHQ1NLT19tdXRhbnRzQG1ldGEuZGF0YSRnZW5vdHlwZSA9PSAiV1QiLCBdKQpHQ1NLT19tdXRhbnRzX3d0b25seSA8LSBzdWJzZXQoR0NTS09fbXV0YW50cywgY2VsbHMgPSBzczJfd3RfY2VsbHMpCmBgYAoKY3JlYXRlIGxpc3QgYW5kIG5vcm1hbGlzZToKYGBge3IgaW50ZWdyYXRpb24gbm9ybWFsaXNlfQojIyBtYWtlIGxpc3QKdGVueC5qdXN0d3QubGlzdCA8LSBsaXN0KHRlbnhfNWtfY291bnRzX3RvX2ludGVncmF0ZSwgR0NTS09fbXV0YW50c193dG9ubHkpCgojIyBwcmVwYXJlIGRhdGEKZm9yIChpIGluIDE6bGVuZ3RoKHRlbnguanVzdHd0Lmxpc3QpKSB7CiAgICB0ZW54Lmp1c3R3dC5saXN0W1tpXV0gPC0gTm9ybWFsaXplRGF0YSh0ZW54Lmp1c3R3dC5saXN0W1tpXV0sIHZlcmJvc2UgPSBGQUxTRSkKICAgIHRlbnguanVzdHd0Lmxpc3RbW2ldXSA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyh0ZW54Lmp1c3R3dC5saXN0W1tpXV0sIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgCiAgICAgICAgbmZlYXR1cmVzID0gMjAwMCwgdmVyYm9zZSA9IEZBTFNFKQogICAgYWxsLmdlbmVzIDwtIHJvd25hbWVzKHRlbnguanVzdHd0Lmxpc3RbW2ldXSkKICAgIHRlbnguanVzdHd0Lmxpc3RbW2ldXSA8LSBTY2FsZURhdGEodGVueC5qdXN0d3QubGlzdFtbaV1dLCBmZWF0dXJlcyA9IGFsbC5nZW5lcykKfQpgYGAKCiMjIyBJbnRlZ3JhdGUgb2JqZWN0cwoKYGBge3IgaW50ZWdyYXRpb259CiMjIEZpbmQgYW5jaG9ycwp0ZW54Lmp1c3R3dC5hbmNob3JzIDwtIEZpbmRJbnRlZ3JhdGlvbkFuY2hvcnMob2JqZWN0Lmxpc3QgPSB0ZW54Lmp1c3R3dC5saXN0LCBkaW1zID0gMToyMSwgdmVyYm9zZSA9IEZBTFNFKQoKIyMgSW50ZWdyYXRlIGRhdGEKdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBJbnRlZ3JhdGVEYXRhKGFuY2hvcnNldCA9IHRlbnguanVzdHd0LmFuY2hvcnMsIGRpbXMgPSAxOjIxLCB2ZXJib3NlID0gRkFMU0UsIGZlYXR1cmVzLnRvLmludGVncmF0ZSA9IGdlbmVzX2luX3RlbnhfZGF0YXNldCkKYGBgCgojIDQuIERpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbiB7LnRhYnNldH0KCiMjIyBQQ0EKYGBge3IsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gNX0KIyMgTWFrZSB0aGUgZGVmYXVsdCBhc3NheSBpbnRlZ3JhdGVkCkRlZmF1bHRBc3NheSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkKSA8LSAiaW50ZWdyYXRlZCIKCiMjIFJ1biB0aGUgc3RhbmRhcmQgd29ya2Zsb3cgZm9yIHZpc3VhbGl6YXRpb24gYW5kIGNsdXN0ZXJpbmcKdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBTY2FsZURhdGEodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgdmVyYm9zZSA9IEZBTFNFKQp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIFJ1blBDQSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBucGNzID0gMzAsIHZlcmJvc2UgPSBGQUxTRSkKCiMjIGluc3BlY3QgUENzCkVsYm93UGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBuZGltcyA9IDMwLCByZWR1Y3Rpb24gPSAicGNhIikKYGBgCgojIyMgT3B0aW1pc2VkIFVNQVAKQWZ0ZXIgb3B0aW1pc2F0aW9uLCB0aGUgZm9sbG93aW5nIFVNQVAgY2FuIGJlIGNhbGN1bGF0ZWQ6CmBgYHtyIHVtYXAgcnVuIDIsIGZpZy5oZWlnaHQgPSA3LCBmaWcud2lkdGggPSA3fQojIyBSdW4gb3B0aW1pc2VkIFVNQVAKdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBSdW5VTUFQKHRlbnguanVzdHd0LmludGVncmF0ZWQsIHJlZHVjdGlvbiA9ICJwY2EiLCBkaW1zID0gMToxMCwgbi5uZWlnaGJvcnMgPSA1MCwgc2VlZC51c2UgPSAxMjM0LCBtaW4uZGlzdCA9IDAuNCwgcmVwdWxzaW9uLnN0cmVuZ3RoID0gMC4wMywgbG9jYWwuY29ubmVjdGl2aXR5ID0gMTUwKQpgYGAKCmBgYHtyIHVtYXAgdmlzdWFsaXNlIDJ9CiMjIHBsb3QKZHAxIDwtIERpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgbGFiZWwgPSBUUlVFLCByZXBlbCA9IEZBTFNFLCBwdC5zaXplID0gMC4wNSwgZGltcyA9IGMoMSwyKSwgc3BsaXQuYnkgPSAiZXhwZXJpbWVudCIpICsgCiAgIyMgZml4IHRoZSBheGlzCiAgY29vcmRfZml4ZWQoKSAjKyAKICAjIyByZXZlcnNlIHRoZSBzY2FsZQogICNzY2FsZV95X3JldmVyc2UoKQoKIyMgdmlldwpkcDEKYGBgCgpNYWtlIGZpbmFsIHBsb3RzOgpgYGB7ciwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KCiMjIHNwbGl0IHNldXJhdCBvYmplY3QgdXAKb2IubGlzdCA8LSBTcGxpdE9iamVjdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBzcGxpdC5ieSA9ICJleHBlcmltZW50IikKCiMjIG1ha2UgcGxvdHMgZm9yIGVhY2ggb2JqZWN0CnBsb3QubGlzdCA8LSBsYXBwbHkoWCA9IG9iLmxpc3QsIEZVTiA9IGZ1bmN0aW9uKHgpIHsKICAgIERpbVBsb3QoeCwgZGltcyA9IGMoMSwyKSwgcHQuc2l6ZSA9IDEpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKQp9KQoKY29tcG9zaXRpb25fdW1hcF8xMHggPC0gcGxvdC5saXN0JGB0ZW54XzVrYCArIAogIGNvb3JkX2ZpeGVkKCkgKwogIHRoZW1lX3ZvaWQoKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKHJlcGxpY2F0ZSg0NSwgIiM5OTk5OTkiKSkpICsKICBsYWJzKHRpdGxlID0gcGFzdGUoIjEweCAod2lsZC10eXBlKSIpKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkKCmNvbXBvc2l0aW9uX3VtYXBfc3MyIDwtIHBsb3QubGlzdCRtdXRhbnRzICsKICBjb29yZF9maXhlZCgpICsKICB0aGVtZV92b2lkKCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YyhyZXBsaWNhdGUoNDYsICIjOTk5OTk5IikpKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJTbWFydC1zZXEyICh3aWxkLXR5cGUpIikpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKQoKY29tcG9zaXRpb25fdW1hcCA8LSBjb21wb3NpdGlvbl91bWFwXzEweCArIGNvbXBvc2l0aW9uX3VtYXBfc3MyIAoKY29tcG9zaXRpb25fdW1hcApgYGAKCnNhdmUKYGBge3J9Cmdnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC9jb21wb3NpdGlvbl91bWFwLnBuZyIsIHBsb3QgPSBjb21wb3NpdGlvbl91bWFwLCBkZXZpY2UgPSAicG5nIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSAyMCwgaGVpZ2h0ID0gMjAsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKCmBgYHtyfQojIyBtYWtlIHBsb3RzCiMjIGhvbyBkYXRhc2V0IGNvcnJlbGF0aW9uClVNQVBfaG9vIDwtIERpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgcHQuc2l6ZSA9IDAuMSwgZ3JvdXAuYnkgPSAiUHJlZGljdGlvbi5TcGVhcm1hbi4iLCBkaW1zID0gYygxLDIpKSArCiAgY29vcmRfZml4ZWQoKSArIAogIHRoZW1lX3ZvaWQoKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJIb28gUHJlZGljdGVkIFRpbWVwb2ludCIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBpbmZlcm5vKDEyKSkgICsKICBsYWJzKGNvbG91ciA9ICJob3VyIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTApKQoKIyMgYXAyZyB0aW1lY291cnNlIGluIHRoaXMgcGFwZXIgY29ycmVsYXRpb24KVU1BUF9rYXNpYSA8LSBEaW1QbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIHB0LnNpemUgPSAwLjEsIGdyb3VwLmJ5ID0gIlByZWRpY3Rpb24uU3BlYXJtYW4uX0thc2lhIiwgZGltcyA9IGMoMSwyKSkgKwogIGNvb3JkX2ZpeGVkKCkgKyAKICB0aGVtZV92b2lkKCkgKwogIGxhYnModGl0bGUgPSBwYXN0ZSgiQVAyRyBUaW1lY291cnNlIFByZWRpY3RlZCBUaW1lcG9pbnQiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gaW5mZXJubygxMCkpICArCiAgbGFicyhjb2xvdXIgPSAiaG91ciIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgbGVnZW5kLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTEwKSkKCiMjIGNvbWJpbmUKdW1hcF9idWxrIDwtIHdyYXBfcGxvdHMoVU1BUF9ob28sIFVNQVBfa2FzaWEsIG5jb2wgPSAyKQoKIyMgcHJpbnQKdW1hcF9idWxrCmBgYAoKIyA1LiBDbHVzdGVyaW5nIHsudGFic2V0fSAKCiMjIyBHZW5lcmF0ZSBjbHVzdGVycwoKYGBge3J9CiMjIGdlbmVyYXRlIG5ldyBjbHVzdGVycyBhdCBsb3cgcmVzb2x1dGlvbgp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIEZpbmROZWlnaGJvcnModGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IDE6MTksIHJlZHVjdGlvbiA9ICJwY2EiKQp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIEZpbmRDbHVzdGVycyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCByZXNvbHV0aW9uID0gMiwgcmFuZG9tLnNlZWQgPSA0MiwgYWxnb3JpdGhtID0gMikKYGBgCgojIyMgdmlzdWFsaXNlIGNsdXN0ZXJzCgpgYGB7cn0KRGltUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUsIHJlcGVsID0gRkFMU0UsIGxhYmVsID0gVFJVRSkKYGBgCgpNYWtlIGluZGl2aWR1YWwgcGxvdHMgaGlnaGxpZ2h0aW5nIHdoZXJlIGNlbGxzIGluIGVhY2ggY2x1c3RlciBmYWxsCmBgYHtyLCBlY2hvID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMjIGZvciBsb29wIHdoaWNoIHRha2VzIGVhY2ggY2x1c3RlciBhbmQgbWFrZXMgYSBsaXN0IG9mIGNlbGxzIGFuZCB0aGVuIHBsb3RzIGEgaGlnaGxpZ2h0ZWQgcGxvdCBhbmQgYWRkcyBpdCB0byBhIGxpc3QKCiMjIG1ha2UgYSBibGFuayBsaXN0Cmxpc3RfVU1BUHNfYnlfY2x1c3RlciA8LSB2ZWN0b3IobW9kZSA9ICJsaXN0IiwgbGVuZ3RoID0gbGVuZ3RoKGxldmVscyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRpbnRlZ3JhdGVkX3Nubl9yZXMuMikpKQoKIyMgZm9yIGxvb3AKZm9yKGkgaW4gc2VxX2Fsb25nKGxldmVscyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRpbnRlZ3JhdGVkX3Nubl9yZXMuMikpKXsKICAjIyBtYWtlIGEgbGlzdCBvZiBjZWxscwogIGxpc3Rfb2ZfY2VsbHMgPC0gcm93bmFtZXModGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGFbd2hpY2godGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkaW50ZWdyYXRlZF9zbm5fcmVzLjIgPT0gbGV2ZWxzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJGludGVncmF0ZWRfc25uX3Jlcy4yKVtpXSksIF0pCiAgdW1hcF9wbG90IDwtIERpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgbGFiZWwgPSBGQUxTRSwgcmVwZWwgPSBUUlVFLCBwdC5zaXplID0gMC4xLCBjZWxscy5oaWdobGlnaHQgPSBsaXN0X29mX2NlbGxzLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIpICsKICAgICMjIGZpeCBjb29yZGluYXRlcwogICAgY29vcmRfZml4ZWQoKSArIAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiI0QzRDNEMyIsICIjMUQxNTY0IikpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJjbHVzdGVyIiwgbGV2ZWxzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJGludGVncmF0ZWRfc25uX3Jlcy4yKVtpXSkpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKICAjIyBhZGQgdG8gdGhlIGxpc3QKICBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbW2ldXSA8LSB1bWFwX3Bsb3QKfQoKIyMgY2hlY2sgbnVtYmVyIG9mIGNsdXN0ZXJzCmxlbmd0aChsaXN0X1VNQVBzX2J5X2NsdXN0ZXIpCmBgYAoKcGxvdApgYGB7ciwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KIyMgdGhpcyBmdW5jdGlvbiB3cml0ZXMgdGhlIG5leHQgYml0IG9mIGNvZGUgZm9yIHlvdQojIyBwdXQgaXQgaW50byB0aGUgY29uc29sZSBhbmQgcGFzdGUgdGhlIHJlc3BvbnNlCiNwbG90eSA8LSBjKCkKI2ZvcihpIGluIHNlcV9hbG9uZyhsZXZlbHModGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzKSkpewojICBwbG90eSA8LSBwYXN0ZTAocGxvdHksICJsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWyIsIGksICJdXSIsICIgKyAiKQojfQoKIyMgcGxvdApsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzFdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMl1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1szXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzRdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbNV1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s2XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzddXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbOF1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s5XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzEwXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzExXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzEyXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzEzXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE0XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE1XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE2XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE3XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE4XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE5XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIwXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIxXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIyXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIzXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzI0XV0KYGBgCgojIyMgRmluZCBNYXJrZXJzCgpgYGB7cn0KRGVmYXVsdEFzc2F5KHRlbnguanVzdHd0LmludGVncmF0ZWQpIDwtICJSTkEiCiMgZmluZCBtYXJrZXJzIGZvciBldmVyeSBjbHVzdGVyIGNvbXBhcmVkIHRvIGFsbCByZW1haW5pbmcgY2VsbHMsIHJlcG9ydCBvbmx5IHRoZSBwb3NpdGl2ZSBvbmVzCnBiLm1hcmtlcnMgPC0gRmluZEFsbE1hcmtlcnModGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgb25seS5wb3MgPSBUUlVFLCBtaW4ucGN0ID0gMC4yNSwgbG9nZmMudGhyZXNob2xkID0gMC4yNSkKcGIubWFya2VycyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHRvcF9uKG4gPSA1LCB3dCA9IGF2Z19sb2dGQykKYGBgCgpgYGB7ciwgUi5vcHRpb25zID0gbGlzdCh3aWR0aCA9IDMwMCl9Cm1hcmtlcnNfc3Vic2V0IDwtIHBiLm1hcmtlcnMgJT4lIGdyb3VwX2J5KGNsdXN0ZXIpICU+JSB0b3BfbihuID0gMjAsIHd0ID0gYXZnX2xvZ0ZDKQptYXJrZXJzX3N1YnNldF9hbm5vdGF0ZWQgPC0gbWVyZ2UobWFya2Vyc19zdWJzZXQsIGdlbmVfYW5ub3RhdGlvbnMsICBieS54ID0gImdlbmUiLCBieS55ID0gIkdlbmUuSUQiLCBhbGwgPSBGQUxTRSkKbWFya2Vyc19zdWJzZXRfYW5ub3RhdGVkClZpZXcobWFya2Vyc19zdWJzZXRfYW5ub3RhdGVkKQpgYGAKCiMjIyB2aXN1YWxpc2UgbWFya2VycwoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMjIGdldCB0aGUgdG9wIDEwIGZvciBlYWNoIGNsdXN0ZXIKdG9wMTAgPC0gcGIubWFya2VycyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHRvcF9uKG4gPSAxMCwgd3QgPSBhdmdfbG9nRkMpCgojIyBzY2FsZSBkYXRhIGlzIG1pc3NpbmcgLSBidXQgb3JpZ2luYWwgZGZzIGhhdmUgc2NhbGUuZGF0YQojIGRmX3NjYWxlZCA8LSBhcy5tYXRyaXgodHJhbnNmb3JtKG1lcmdlKGFzLmRhdGEuZnJhbWUodGVueC5qdXN0d3QubGlzdFtbMV1dQGFzc2F5cyRSTkFAc2NhbGUuZGF0YSksIGFzLmRhdGEuZnJhbWUodGVueC5qdXN0d3QubGlzdFtbMl1dQGFzc2F5cyRSTkFAc2NhbGUuZGF0YSksIGJ5ID0gMCwgYWxsPUZBTFNFKSwgcm93Lm5hbWVzPVJvdy5uYW1lcywgUm93Lm5hbWVzPU5VTEwpKQojIHRlbnguanVzdHd0LmludGVncmF0ZWRAYXNzYXlzJFJOQUBzY2FsZS5kYXRhIDwtIGRmX3NjYWxlZAoKIyMgc2NhbGUgZGF0YSBpbiBSTkEgc2xvdAphbGwuZ2VuZXMgPC0gcm93bmFtZXModGVueC5qdXN0d3QuaW50ZWdyYXRlZCkKdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBTY2FsZURhdGEodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgdmFycy50by5yZWdyZXNzID0gJ2V4cGVyaW1lbnQnLCBmZWF0dXJlcyA9IGFsbC5nZW5lcykKCiMjIGhlYXRtYXAKRG9IZWF0bWFwKHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gdG9wMTAkZ2VuZSkgKyBOb0xlZ2VuZCgpCmBgYAoKIyA2LiBEZWZpbmUgQ2x1c3RlciBJZGVudGl0aWVzIHsudGFic2V0fSAKCiMjIyBEb3duc2FtcGxpbmcKYGBge3J9CiMgIyMgY2hlY2sgbnVtYmVyIG9mIGNlbGxzIGluIGVhY2ggY2x1c3RlcgojIGRmX2NsdXN0ZXJzIDwtIGFzLmRhdGEuZnJhbWUodGFibGUodGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkaW50ZWdyYXRlZF9zbm5fcmVzLjIpKQojIHBsb3QoZGZfY2x1c3RlcnMpCiMgCiMgIyMgZG93bnNhbXBsZSB1c2luZyBhcHByb3ByaWF0ZSBtZXRyaWNzCiMgdGVueC5qdXN0d3QuaW50ZWdyYXRlZC5kb3duc2FtcGxlZCA8LSBzdWJzZXQodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZG93bnNhbXBsZSA9IDEwMCkKIyAgIAojICMjIGluc3BlY3QgcGxvdAojIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQuZG93bnNhbXBsZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0xNDM3NTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiMgICB0aGVtZV92b2lkKCkgKyAKIyAgIGxhYnModGl0bGUgPSBwYXN0ZSgiQVAyRyAoQ29tbWl0bWVudCkiKSkgKyAKIyAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAojICAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkKYGBgCgojIyMgTWFya2VyIEdlbmVzCgp1c2VmdWwgdG9vbHMgZm9yIGFsbCBwbG90cwpgYGB7cn0KIyMgZGVmaW5lIG1hbGUgYW5kIGZlbWFsZSBzeW1ib2wKZmVtYWxlX3N5bWJvbCA8LSBpbnRUb1V0ZjgoOTc5MikKbWFsZV9zeW1ib2wgPC0gaW50VG9VdGY4KDk3OTQpCgojIyBkZWZpbmUgY29sb3VyIHBhbAptYXJrZXJfZ2VuZV9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygiI0QzRDNEMyIsICIjMUQxNTY0IikpKDUwKQpgYGAKCiMjIyMgRXhwcmVzc2lvbiAtIGN1dG9mZnMgLSBwdXJwbGUKCmBgYHtyLCBmaWcuaGVpZ2h0ID0gMTUsIGZpZy53aWR0aCA9IDE1fQoKbWFya2VyX2dlbmVfcGxvdF9DQ1AyIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTEzMTk1MDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKGNjcDIpfihGZW1hbGUpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTYuMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCgptYXJrZXJfZ2VuZV9wbG90X01HMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTA0MTYxMDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArCiAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhtZzEpfihNYWxlKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9Ni4wKSwgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCgptYXJrZXJfZ2VuZV9wbG90X0FQMkcgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMTQzNzUwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMoYXAyZyl+KENvbW1pdG1lbnQpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTYuMCksIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCgptYXJrZXJfZ2VuZV9wbG90X01TUDEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMDgzMTAwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMobXNwMSl+KFNjaGl6b250KSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT02LjApLCBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQoKbWFya2VyX2dlbmVfcGxvdF9NU1A4IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTExMDIyMDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKG1zcDgpfihBc2V4dWFsKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT02LjApLCBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQoKbWFya2VyX2dlbmVfcGxvdF9TQlAxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTExMDEzMDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMoU0JQMSl+KFJpbmcpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTYuMCksIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCgptYXJrZXJfZ2VuZV9wbG90X0ZBTUIgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMDcyMjYwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhmYW0tYjIpfihSaW5nKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT02LjApLCBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQoKbWFya2VyX2dlbmVfcGxvdF9PUkMxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTA2MDIwMDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMob3JjMSl+KEROQX5yZXBsaWNhdGlvbikpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9Ni4wKSwgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkKCm1hcmtlcl9nZW5lX3Bsb3RfQ0RQSzUgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTEzNTE1MDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhjZHBrNSl+KFNjaGl6b250KSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT02LjApLCBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQoKbWFya2VyX2dlbmVfcGxvdF9NQ000IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0xNDE1NjAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC41LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMobWNtNCl+KEROQX5yZXBsaWNhdGlvbikpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9Ni4wKSwgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkKCiMgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKQoKIyMgcGxvdAojIyBjb3dwbG90IG1ldGhvZAptYXJrZXJfZ2VuZV9wbG90X2FsbCA8LSBwbG90X2dyaWQobWFya2VyX2dlbmVfcGxvdF9GQU1CLCBtYXJrZXJfZ2VuZV9wbG90X01TUDgsIG1hcmtlcl9nZW5lX3Bsb3RfTVNQMSwgbWFya2VyX2dlbmVfcGxvdF9BUDJHLCBtYXJrZXJfZ2VuZV9wbG90X0NDUDIsIG1hcmtlcl9nZW5lX3Bsb3RfTUcxLCBtYXJrZXJfZ2VuZV9wbG90X0hTUDcwLCBucm93PTMpCgptYXJrZXJfZ2VuZV9wbG90X2FsbApgYGAKCiMjIyBNdXRhbnQgR2VuZXMKCiMjIyMgRXhwcmVzc2lvbiAtIHdpdGggY3V0b2ZmcwoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMgUEJBTktBLTE0MTgxMDAgICAgICAgIEdDU0tPLTE3ICBGRDMgICAKIyBQQkFOS0EtMDEwMjQwMCAgICAgICAgIEdDU0tPLTIgIE1ENCAKIyBQQkFOS0EtMDcxNjUwMCAgICAgICAgR0NTS08tMTkgIE1ENSAKIyBQQkFOS0EtMTQzNTIwMCAgICAgICAgR0NTS08tMjAgIEZENCAKIyBQQkFOS0EtMDkwMjMwMCAgICAgICAgR0NTS08tMTMgIEZEMgojIFBCQU5LQS0wNDEzNDAwICAgIEdDU0tPLTEwXzgyMCAgTUQzCiMgUEJBTktBLTA4MjgwMDAgICAgICAgICBHQ1NLTy0zICBHRDEKIyBQQkFOS0EtMTMwMjcwMCAgICAgICBHQ1NLTy1vb20gIE1EMSAKIyBQQkFOS0EtMTQ0NzkwMCAgICAgICAgR0NTS08tMjkgIE1EMgojIFBCQU5LQS0xNDU0ODAwICAgICAgICBHQ1NLTy0yMSAgRkQxCiMgUEJBTktBLTExNDQ4MDAgICAgICAgIEdDU0tPLTI4ICBGRDUKCgptYXJrZXJfZ2VuZV9wbG90X2ZkMyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0xNDE4MTAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC41LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMoZmQzKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCiAgICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICAjYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X21kNCA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0wMTAyNDAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhtZDQpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCiAgICAgICAgICAgICAgICAgICAgICAjIyBhZGQgc2V4IHN5bWJvbHMKICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X21kNSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0wNzE2NTAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC41LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKG1kNSkpKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpIAogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF9mZDQgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMTQzNTIwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMoZmQ0KSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT03KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkgCiAgICAgICAgICAgICAgICAgICAgICAgIyMgYWRkIHNleCBzeW1ib2xzCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X2ZkMiA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0wOTAyMzAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhmZDIpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICMgKyBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF9tZDMgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMDQxMzQwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhtZDMpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X2dkMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTA4MjgwMDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMoZ2QxKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT03KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkKICAgICAgICAgICAgICAgICAgICAgICAjIyBhZGQgc2V4IHN5bWJvbHMKICAgICAgICAgICAgICAgICAgICAgICAjYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICAgICAgICAgICAgICAgICAgICAgICAjYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfbWQxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTEzMDI3MDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhtZDEpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF9tZDIgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTE0NDc5MDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhtZDIpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF9mZDEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMTQ1NDgwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhmZDEpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKIyNvcmlnaW5hbCBsYWJlbDoKIyBsYWJzKHRpdGxlID0gcGFzdGUoIihDQ1AyOyBGZW1hbGUpIiwiXG4iLCAiUEJBTktBXzEzMTk1MDAiKSkKIyBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKQojIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpCgojIyBtYWtlIGNvbXBvc2l0ZSBwbG90Cm11dGFudF9leHByZXNzaW9uX2NvbXBvc2l0ZSA8LSB3cmFwX3Bsb3RzKG1hcmtlcl9nZW5lX3Bsb3RfZ2QxICwgbWFya2VyX2dlbmVfcGxvdF9tZDEgLCBtYXJrZXJfZ2VuZV9wbG90X21kMiAsIG1hcmtlcl9nZW5lX3Bsb3RfbWQzICwgbWFya2VyX2dlbmVfcGxvdF9tZDQgLCBtYXJrZXJfZ2VuZV9wbG90X21kNSAsIG1hcmtlcl9nZW5lX3Bsb3RfZmQxICwgbWFya2VyX2dlbmVfcGxvdF9mZDIgLCBtYXJrZXJfZ2VuZV9wbG90X2ZkMyAsIG1hcmtlcl9nZW5lX3Bsb3RfZmQ0LCBuY29sID0gNCkKICAgICAgICAgICAKIyMgcHJpbnQKbXV0YW50X2V4cHJlc3Npb25fY29tcG9zaXRlCmBgYAoKc2F2ZQpgYGB7cn0KZ2dzYXZlKCIuLi9pbWFnZXNfdG9fZXhwb3J0L0FMTF9DRUxMU193dF9nZW5lX2V4cHJlc3Npb24ucG5nIiwgcGxvdCA9IG11dGFudF9leHByZXNzaW9uX2NvbXBvc2l0ZSwgZGV2aWNlID0gInBuZyIsIHBhdGggPSBOVUxMLCBzY2FsZSA9IDEsIHdpZHRoID0gMjEsIGhlaWdodCA9IDI5LjcsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKCmBgYHtyLCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQojIFBCQU5LQS0xNDE4MTAwICAgICAgICBHQ1NLTy0xNyAgRkQzICAgCiMgUEJBTktBLTAxMDI0MDAgICAgICAgICBHQ1NLTy0yICBNRDMgCiMgUEJBTktBLTA3MTY1MDAgICAgICAgIEdDU0tPLTE5ICBNRDQgCiMgUEJBTktBLTE0MzUyMDAgICAgICAgIEdDU0tPLTIwICBGRDQgCiMgUEJBTktBLTA5MDIzMDAgICAgICAgIEdDU0tPLTEzICBGRDIKIyBQQkFOS0EtMDQxMzQwMCAgICBHQ1NLTy0xMF84MjAgIE1ENQojIFBCQU5LQS0wODI4MDAwICAgICAgICAgR0NTS08tMyAgR0QxCiMgUEJBTktBLTEzMDI3MDAgICAgICAgR0NTS08tb29tICBNRDEgCiMgUEJBTktBLTE0NDc5MDAgICAgICAgIEdDU0tPLTI5ICBNRDIKIyBQQkFOS0EtMTQ1NDgwMCAgICAgICAgR0NTS08tMjEgIEZEMQojIFBCQU5LQS0xMTQ0ODAwICAgICAgICBHQ1NLTy0yOCAgRkQ1CgoKbWFya2VyX2dlbmVfcGxvdF8xNyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0xNDE4MTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBtaW4uY3V0b2ZmID0gInExMCIsIG1heC5jdXRvZmYgPSAicTkwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoImZkMyIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzIgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDEwMjQwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgbWluLmN1dG9mZiA9ICJxMTAiLCBtYXguY3V0b2ZmID0gInE5MCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDMiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF8xOSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wNzE2NTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBtaW4uY3V0b2ZmID0gInExMCIsIG1heC5jdXRvZmYgPSAicTkwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kNCIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzIwIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTE0MzUyMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIG1pbi5jdXRvZmYgPSAicTEwIiwgbWF4LmN1dG9mZiA9ICJxOTAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQ0IikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMTMgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDkwMjMwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgbWluLmN1dG9mZiA9ICJxMTAiLCBtYXguY3V0b2ZmID0gInE5MCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDIiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF8xMCA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wNDEzNDAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBtaW4uY3V0b2ZmID0gInExMCIsIG1heC5jdXRvZmYgPSAicTkwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kNSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzMgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDgyODAwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgbWluLmN1dG9mZiA9ICJxMTAiLCBtYXguY3V0b2ZmID0gInE5MCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJnZDEiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF9vb20gPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTMwMjcwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgbWluLmN1dG9mZiA9ICJxMTAiLCBtYXguY3V0b2ZmID0gInE5MCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDEiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF8yOSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0xNDQ3OTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBtaW4uY3V0b2ZmID0gInExMCIsIG1heC5jdXRvZmYgPSAicTkwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMiIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzIxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTE0NTQ4MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIG1pbi5jdXRvZmYgPSAicTEwIiwgbWF4LmN1dG9mZiA9ICJxOTAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQxIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCiMjb3JpZ2luYWwgbGFiZWw6CiMgbGFicyh0aXRsZSA9IHBhc3RlKCIoQ0NQMjsgRmVtYWxlKSIsIlxuIiwgIlBCQU5LQV8xMzE5NTAwIikpCgojIyBtYWtlIGNvbXBvc2l0ZSBwbG90Cm11dGFudF9leHByZXNzaW9uX2NvbXBvc2l0ZSA8LSB3cmFwX3Bsb3RzKG1hcmtlcl9nZW5lX3Bsb3RfMTcgLCBtYXJrZXJfZ2VuZV9wbG90XzIgLCBtYXJrZXJfZ2VuZV9wbG90XzE5ICwgbWFya2VyX2dlbmVfcGxvdF8yMCAsIG1hcmtlcl9nZW5lX3Bsb3RfMTMgLCBtYXJrZXJfZ2VuZV9wbG90XzEwICwgbWFya2VyX2dlbmVfcGxvdF8zICwgbWFya2VyX2dlbmVfcGxvdF9vb20gLCBtYXJrZXJfZ2VuZV9wbG90XzI5ICwgbWFya2VyX2dlbmVfcGxvdF8yMSAsIG5jb2wgPSA0KQogICAgICAgICAgIAojIyBwcmludAptdXRhbnRfZXhwcmVzc2lvbl9jb21wb3NpdGUKYGBgCgoKCiMgNy4gUHNldWRvdGltZSBvbiBhbGwgY2VsbHMgey50YWJzZXR9CgojIyMgUHNldWRvdGltZSBjYWxjdWxhdGlvbgoKYGBge3J9CiMjIGV4dHJhY3QgZGF0YSBmcm9tIFNldXJhdApzZXVyYXQub2JqZWN0LmFsbCA8LSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkCiMgY291bnRzCmRhdGEgPC0gYXMoYXMubWF0cml4KEdldEFzc2F5RGF0YShzZXVyYXQub2JqZWN0LmFsbCwgYXNzYXkgPSAiaW50ZWdyYXRlZCIsIHNsb3QgPSAiZGF0YSIpKSwgJ3NwYXJzZU1hdHJpeCcpCiMgbWV0YSBkYXRhCnBkIDwtIGRhdGEuZnJhbWUoc2V1cmF0Lm9iamVjdC5hbGxAbWV0YS5kYXRhKQoKIyMga2VlcCBvbmx5IHRoZSBjb2x1bW5zIHRoYXQgYXJlIHJlbGV2YW50CiNwRGF0YSA8LSBwZCAlPiUgc2VsZWN0KG9yaWcuaWRlbnQsIG5Db3VudF9STkEsIG5GZWF0dXJlX1JOQSkKIyMgYWRkIGdlbmUgc2hvcnQgbmFtZQpmRGF0YSA8LSBkYXRhLmZyYW1lKGdlbmVfc2hvcnRfbmFtZSA9IHJvdy5uYW1lcyhkYXRhKSwgcm93Lm5hbWVzID0gcm93Lm5hbWVzKGRhdGEpKQoKIyMgQ29uc3RydWN0IG1vbm9jbGUgY2RzCm1vbm9jbGUub2JqZWN0LmFsbCA8LSBuZXdfY2VsbF9kYXRhX3NldChleHByZXNzaW9uX2RhdGEgPSBkYXRhLCBjZWxsX21ldGFkYXRhID0gcGQsIGdlbmVfbWV0YWRhdGEgPSBmRGF0YSkKIyMgcHJlcHJvY2Vzcwptb25vY2xlLm9iamVjdC5hbGwgPSBwcmVwcm9jZXNzX2Nkcyhtb25vY2xlLm9iamVjdC5hbGwsIG51bV9kaW0gPSAxMDAsIG5vcm1fbWV0aG9kID0gIm5vbmUiKQojIyBwbG90IHZhcmlhbmNlIGV4cGxhaW5lZCBwbG90CiNwbG90X3BjX3ZhcmlhbmNlX2V4cGxhaW5lZChtb25vY2xlLm9iamVjdC5hbGwpCiMjIG1ha2UgbW9ub2NsZSBVTUFQCiNtb25vY2xlLm9iamVjdC5hbGwgPSByZWR1Y2VfZGltZW5zaW9uKG1vbm9jbGUub2JqZWN0LmFsbCwgcmVkdWN0aW9uX21ldGhvZCA9ICJVTUFQIiwgcHJlcHJvY2Vzc19tZXRob2QgPSAiUENBIiwgdW1hcC5tZXRyaWMgPSAiZXVjbGlkZWFuIiwgdW1hcC5uX25laWdoYm9ycyA9IDIwLCB1bWFwLm1pbl9kaXN0ID0gMC41LCB2ZXJib3NlID0gRkFMU0UpCiNwbG90X2NlbGxzKG1vbm9jbGUub2JqZWN0LmFsbCkKCiMjIGFkZCBVTUFQIGZyb20gU2V1cmF0Cm1vbm9jbGUub2JqZWN0LmFsbEBpbnRfY29sRGF0YUBsaXN0RGF0YSRyZWR1Y2VkRGltc0BsaXN0RGF0YVtbIlVNQVAiXV0gPC1zZXVyYXQub2JqZWN0LmFsbEByZWR1Y3Rpb25zW1sidW1hcCJdXUBjZWxsLmVtYmVkZGluZ3MgCnBsb3RfY2VsbHMobW9ub2NsZS5vYmplY3QuYWxsKQoKIyMgY2x1c3Rlcgptb25vY2xlLm9iamVjdC5hbGwgPSBjbHVzdGVyX2NlbGxzKG1vbm9jbGUub2JqZWN0LmFsbCkKCiMjIHBsb3QgY2x1c3RlcnMKcGxvdF9jZWxscyhtb25vY2xlLm9iamVjdC5hbGwsIGNvbG9yX2NlbGxzX2J5PSJwYXJ0aXRpb24iLCBncm91cF9jZWxsc19ieT0icGFydGl0aW9uIiwgIHggPSAxLCB5ID0gMikKCiMjIHJlZHVjZSBwYXJ0aXRpb25zIHRvIDEKbW9ub2NsZS5vYmplY3QuYWxsQGNsdXN0ZXJzJFVNQVAkcGFydGl0aW9uc1ttb25vY2xlLm9iamVjdC5hbGxAY2x1c3RlcnMkVU1BUCRwYXJ0aXRpb25zID09ICIyIl0gPC0gIjEiCgojbWFwIHBzZXVkb3RpbWUKbW9ub2NsZS5vYmplY3QuYWxsID0gbGVhcm5fZ3JhcGgobW9ub2NsZS5vYmplY3QuYWxsLCBsZWFybl9ncmFwaF9jb250cm9sPWxpc3QobmNlbnRlcj01NTAsIG1pbmltYWxfYnJhbmNoX2xlbiA9IDE1KSwgdXNlX3BhcnRpdGlvbiA9IEZBTFNFKQoKcGxvdF9jZWxscyhtb25vY2xlLm9iamVjdC5hbGwsIGNvbG9yX2NlbGxzX2J5PSJwYXJ0aXRpb24iLCBncm91cF9jZWxsc19ieT0icGFydGl0aW9uIiwgIHggPSAxLCB5ID0gMikKCiMjIGEgaGVscGVyIGZ1bmN0aW9uIHRvIGlkZW50aWZ5IHRoZSByb290IHByaW5jaXBhbCBwb2ludHM6CiMjIG1ha2UgY2x1c3RlciAyIHRoZSByb290CiMgZ2V0X2VhcmxpZXN0X3ByaW5jaXBhbF9ub2RlIDwtIGZ1bmN0aW9uKGNkcywgdGltZV9iaW49IjciKXsKIyAgIGNlbGxfaWRzIDwtIHdoaWNoKGNvbERhdGEoY2RzKVssICJzZXVyYXRfY2x1c3RlcnMiXSA9PSB0aW1lX2JpbikKIyAgIGNsb3Nlc3RfdmVydGV4IDwtCiMgICBjZHNAcHJpbmNpcGFsX2dyYXBoX2F1eFtbIlVNQVAiXV0kcHJfZ3JhcGhfY2VsbF9wcm9qX2Nsb3Nlc3RfdmVydGV4CiMgICBjbG9zZXN0X3ZlcnRleCA8LSBhcy5tYXRyaXgoY2xvc2VzdF92ZXJ0ZXhbY29sbmFtZXMoY2RzKSwgXSkKIyAgIHJvb3RfcHJfbm9kZXMgPC0KIyAgIGlncmFwaDo6VihwcmluY2lwYWxfZ3JhcGgoY2RzKVtbIlVNQVAiXV0pJG5hbWVbYXMubnVtZXJpYyhuYW1lcwojICAgKHdoaWNoLm1heCh0YWJsZShjbG9zZXN0X3ZlcnRleFtjZWxsX2lkcyxdKSkpKV0KIyAgIAojICAgcm9vdF9wcl9ub2RlcwojIH0KCiMjIGNhbGN1bGF0ZSBwc2V1ZG90aW1lCiNtb25vY2xlLm9iamVjdC5hbGwgPSBvcmRlcl9jZWxscyhtb25vY2xlLm9iamVjdC5hbGwsIHJvb3RfcHJfbm9kZXM9Z2V0X2VhcmxpZXN0X3ByaW5jaXBhbF9ub2RlKG1vbm9jbGUub2JqZWN0LmFsbCkpCm1vbm9jbGUub2JqZWN0LmFsbCA9IG9yZGVyX2NlbGxzKG1vbm9jbGUub2JqZWN0LmFsbCkKIyMgdXNlZCA1IHBvaW50cyBhdCB0aGUgYmVnaW5uaW5nCgoKIyMgcGxvdAp1bWFwX3B0IDwtIHBsb3RfY2VsbHMobW9ub2NsZS5vYmplY3QuYWxsLCBjb2xvcl9jZWxsc19ieSA9ICJwc2V1ZG90aW1lIiwgbGFiZWxfY2VsbF9ncm91cHM9RkFMU0UsIGNlbGxfc2l6ZSA9IDEsIHggPSAxLCB5ID0gMiwgbGFiZWxfYnJhbmNoX3BvaW50cz1GQUxTRSwgbGFiZWxfbGVhdmVzPUZBTFNFLCBsYWJlbF9ncm91cHNfYnlfY2x1c3Rlcj1GQUxTRSwgbGFiZWxfcm9vdHMgPSBGQUxTRSkgKwogIGNvb3JkX2ZpeGVkKCkgKwogIHRoZW1lX3ZvaWQoKSArCiAgbGFicyh0aXRsZSA9ICIiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZT0yMCksIGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIiwgbGVnZW5kLnRpdGxlPWVsZW1lbnRfdGV4dCAoc2l6ZT0yMCksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTIwKSkgKyAKICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMTAsIGJhcmhlaWdodCA9IDIsIHRpdGxlID0gIlBzZXVkb3RpbWUiKSkKCiMjIHZpZXcgcGxvdAp1bWFwX3B0CgojIyBoZWxwIHdhcyBvYnRhaW5lZCBmcm9tIGhlcmUKIyMgaHR0cHM6Ly9naXRodWIuY29tL3NhdGlqYWxhYi9zZXVyYXQvaXNzdWVzLzE2NTgKYGBgCgpzYXZlCmBgYHtyfQpnZ3NhdmUoIi4uL2ltYWdlc190b19leHBvcnQvVU1BUF9wdF93dC5wbmciLCBwbG90ID0gdW1hcF9wdCwgZGV2aWNlID0gInBuZyIsIHBhdGggPSBOVUxMLCBzY2FsZSA9IDEsIHdpZHRoID0gMjAsIGhlaWdodCA9IDIwLCB1bml0cyA9ICJjbSIsIGRwaSA9IDMwMCwgbGltaXRzaXplID0gVFJVRSkKYGBgCgojIyMgZ2dhbmltbmF0ZSBHSUYgb2YgcHNldW9kdGltZQoKYGBge3J9CiNpbnN0YWxsLnBhY2thZ2VzKCJnZ2FuaW1hdGUiKQpsaWJyYXJ5KGdnYW5pbWF0ZSkKI2luc3RhbGwucGFja2FnZXMoImdpZnNraSIpCiNpbnN0YWxsLnBhY2thZ2VzKCJhdiIpCiNsaWJyYXJ5KGdpZnNraSkKI2xpYnJhcnkoYXYpCgojIyBtYWtlIGRhdGFmcmFtZSBmb3IgcGxvdHRpbmcKIyMgZXh0cmFjdCBkYXRhIGZvciBHR3Bsb3QgdmVyc2lvbiBvZiB0aGlzCmRmX2FuaW1hdGlvbiA8LSBhcy5kYXRhLmZyYW1lKG1vbm9jbGUub2JqZWN0LmFsbEBpbnRfY29sRGF0YUBsaXN0RGF0YSRyZWR1Y2VkRGltc0BsaXN0RGF0YVtbIlVNQVAiXV0pCiMjIGFkZCBwdCB0byB0aGlzIGRhdGEgZnJhbWU6CnB0X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHBzZXVkb3RpbWUobW9ub2NsZS5vYmplY3QuYWxsLCByZWR1Y3Rpb25fbWV0aG9kID0gIlVNQVAiKSkKZGZfYW5pbWF0aW9uIDwtIG1lcmdlKGRmX2FuaW1hdGlvbiwgcHRfdmFsdWVzLCBieT0icm93Lm5hbWVzIikgCnJvd25hbWVzKGRmX2FuaW1hdGlvbikgPC0gZGZfYW5pbWF0aW9uJFJvdy5uYW1lcwpjb2xuYW1lcyhkZl9hbmltYXRpb24pWzRdIDwtICJwdCIKCiMjIG1ha2UgdGhlIHN0YXRpYyBwbG90CnAgPC0gZ2dwbG90KGRmX2FuaW1hdGlvbiwgYWVzKHggPSBVTUFQXzEsIHkgPSBVTUFQXzIsIGNvbG91ciA9IHB0KSkgKwogIGdlb21fcG9pbnQoKSArCiAgc2NhbGVfY29sb3VyX3ZpcmlkaXNfYyhvcHRpb24gPSAicGxhc21hIikgKwogIGNvb3JkX2ZpeGVkKCkgKwogIHRoZW1lX3ZvaWQoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQojIyB2aWV3IHBsb3QKcGxvdChwKQoKIyMgbWFrZSBhbmltYXRlZCBwbG90CiMjIG1ha2UgYSBjYXRlZ29yeSBmb3IgYW5pbWF0aW9uCiNkZl9hbmltYXRpb24kZ3JvdXAgPC0gY3V0KGRmX2FuaW1hdGlvbiRwdCwgMTUpCgphbmltIDwtIHAgKwogIHRyYW5zaXRpb25fdGltZShwdCkgKwogIHNoYWRvd19tYXJrKCkKCmFuaW1hdGUoYW5pbSwgaGVpZ2h0ID0gMywgd2lkdGggPSAzLCB1bml0cyA9ICJpbiIsIHJlcyA9IDE1MCwgYmcgPSAndHJhbnNwYXJlbnQnKQoKIyMgdG8gY2hhbmdlIHRoZSByZXNvbHV0aW9uIC0gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNDkwNTg1NjcvZGVmaW5lLXNpemUtZm9yLWdpZi1jcmVhdGVkLWJ5LWdnYW5pbWF0ZS1jaGFuZ2UtZGltZW5zaW9uLXJlc29sdXRpb24gCmBgYApTYXZlIGFuaW1hdGlvbgpgYGB7cn0KYW5pbV9zYXZlKCJhbmltYXRlZF9VTUFQX3RyYW5zcGFyZW50X2JnX3d0LmdpZiIsIHBhdGggPSAiLi4vaW1hZ2VzX3RvX2V4cG9ydC8iKQpgYGAKCmBgYHtyfQojIyBleHRyYWN0IHB0IHZhbHVlcwpwdF92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZShwc2V1ZG90aW1lKG1vbm9jbGUub2JqZWN0LmFsbCwgcmVkdWN0aW9uX21ldGhvZCA9ICJVTUFQIikpCgp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIEFkZE1ldGFEYXRhKHRlbnguanVzdHd0LmludGVncmF0ZWQsIHB0X3ZhbHVlcywgIm9sZF9wdF92YWx1ZXMiKQpgYGAKCiMjIyMgRGVmaW5lIGNlbGwgaWRlbnRpdGllcyB3aXRoIGJyYW5jaGVzCgpEZWZpbmUgaWRlbnRpdGllcyBvZiBjZWxscyAKCm1hbGUKYGBge3J9Cm1vbm9jbGUub2JqZWN0X21hbGUgPC0gY2hvb3NlX2dyYXBoX3NlZ21lbnRzKG1vbm9jbGUub2JqZWN0LmFsbCkKYGBgCmZlbWFsZQpgYGB7cn0KbW9ub2NsZS5vYmplY3RfZmVtYWxlIDwtIGNob29zZV9ncmFwaF9zZWdtZW50cyhtb25vY2xlLm9iamVjdC5hbGwpCmBgYApiaXBvdGVudGlhbApgYGB7cn0KbW9ub2NsZS5vYmplY3RfYmlwb3QgPC0gY2hvb3NlX2dyYXBoX3NlZ21lbnRzKG1vbm9jbGUub2JqZWN0LmFsbCkKYGBgCmFzZXh1YWwgKHByZS1icmFuY2gpCmBgYHtyfQptb25vY2xlLm9iamVjdF9hc2V4X3ByZSA8LSBjaG9vc2VfZ3JhcGhfc2VnbWVudHMobW9ub2NsZS5vYmplY3QuYWxsKQpgYGAKYXNleHVhbCBmYXRlCmBgYHtyfQptb25vY2xlLm9iamVjdF9hc2V4X2ZhdGUgPC0gY2hvb3NlX2dyYXBoX3NlZ21lbnRzKG1vbm9jbGUub2JqZWN0LmFsbCkKYGBgCmNoZWNrCmBgYHtyfQpkZl9mcmVxIDwtIGRhdGEuZnJhbWUodGFibGUoYyhjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9tYWxlKSwgY29sbmFtZXMobW9ub2NsZS5vYmplY3RfZmVtYWxlKSwgY29sbmFtZXMobW9ub2NsZS5vYmplY3RfYmlwb3QpLCBjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9hc2V4X3ByZSksIGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2FzZXhfZmF0ZSkpKSkKcGFzdGUoIm51bWJlciBvZiBjZWxscyBpbiBzZXVyYXQgb2JqZWN0IGlzIiwgbGVuZ3RoKGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0LmFsbCkpLCAiLiBUaGUgbnVtYmVyIG9mIGNlbGxzIHNlbGVjdGVkIGhlcmUgd2l0aCBhbiBpZGVudGl0aXR5IGlzIiwgZGltKGRmX2ZyZXEpWzFdKQpkZl9mcmVxIDwtIGRmX2ZyZXFbZGZfZnJlcSRGcmVxID4gMSwgXQpkZl9mcmVxCmBgYApJbnNwZWN0IHdoZXJlIHRoZXNlIG1pc3NpbmcgY2VsbHMgYXJlOgpgYGB7cn0KIyAnJW5pJScgPC0gTmVnYXRlKCclaW4lJykKIyAKIyBub3RfYXNzaWduZWRfY2VsbHMgPC0gY29sbmFtZXMobW9ub2NsZS5vYmplY3QuYWxsKVtjb2xuYW1lcyhtb25vY2xlLm9iamVjdC5hbGwpICVuaSUgYyhjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9tYWxlKSwgY29sbmFtZXMobW9ub2NsZS5vYmplY3RfZmVtYWxlKSwgY29sbmFtZXMobW9ub2NsZS5vYmplY3RfYmlwb3QpLCBjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9hc2V4KSwgY29sbmFtZXMobW9ub2NsZS5vYmplY3RfYXNleF9mYXRlKSldCiMgCiMgRGltUGxvdChzZXVyYXQub2JqZWN0LCByZXBlbCA9IFRSVUUsIGxhYmVsLnNpemUgPSA1LCBwdC5zaXplID0gMC41LCBjZWxscy5oaWdobGlnaHQgPSBub3RfYXNzaWduZWRfY2VsbHMsIGRpbXMgPSBjKDIsMSksIHJlZHVjdGlvbiA9ICJESU1fVU1BUCIpICsKIyAgIGNvb3JkX2ZpeGVkKCkgKyAKIyAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiIzAwMDAwMCIsICIjZjU0ZTFlIikpCmBgYAoKYGBge3J9CiMjIGNyZWF0ZSBhbm5vdGF0aW9uIGRhdGFmcmFtZSBmcm9tIHRoZXNlIHJlc3VsdHM6CmRmX21vbm9jbGVfc2V4ZXMgPC0gcmJpbmQoZGF0YS5mcmFtZSgiY2VsbF9uYW1lIiA9IGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X21hbGUpLCAic2V4IiA9IHJlcCgiTWFsZSIsIGxlbmd0aChjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9tYWxlKSkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmZyYW1lKCJjZWxsX25hbWUiID0gY29sbmFtZXMobW9ub2NsZS5vYmplY3RfZmVtYWxlKSwgInNleCIgPSByZXAoIkZlbWFsZSIsIGxlbmd0aChjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9mZW1hbGUpKSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuZnJhbWUoImNlbGxfbmFtZSIgPSBjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9iaXBvdCksICJzZXgiID0gcmVwKCJCaXBvdGVudGlhbCIsIGxlbmd0aChjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9iaXBvdCkpKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5mcmFtZSgiY2VsbF9uYW1lIiA9IGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2FzZXhfcHJlKSwgInNleCIgPSByZXAoIkFzZXh1YWxfRWFybHkiLCBsZW5ndGgoY29sbmFtZXMobW9ub2NsZS5vYmplY3RfYXNleF9wcmUpKSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuZnJhbWUoImNlbGxfbmFtZSIgPSBjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9hc2V4X2ZhdGUpLCAic2V4IiA9IHJlcCgiQXNleHVhbF9MYXRlIiwgbGVuZ3RoKGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2FzZXhfZmF0ZSkpKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAjZGF0YS5mcmFtZSgiY2VsbF9uYW1lIiA9IG5vdF9hc3NpZ25lZF9jZWxscywgInNleCIgPSByZXAoIlVuYXNzaWduZWQiLCBsZW5ndGgobm90X2Fzc2lnbmVkX2NlbGxzKSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgKQoKZGltKGRmX21vbm9jbGVfc2V4ZXMpCgojIyBvcmRlciBsaWtlIHRoZSBtZXRhZGF0YQpkZl9tb25vY2xlX3NleGVzIDwtIGRmX21vbm9jbGVfc2V4ZXNbbWF0Y2gocm93bmFtZXMobW9ub2NsZS5vYmplY3QuYWxsQGNvbERhdGEpLCBkZl9tb25vY2xlX3NleGVzJGNlbGxfbmFtZSksIF0KCiMjIGFkZCB0aGlzIGJhY2sgaW50byB0aGUgbW9ub2NsZSBvYmplY3QKbW9ub2NsZS5vYmplY3QuYWxsQGNvbERhdGEkU2V4ZXNfbW9ub2NsZSA8LSBkZl9tb25vY2xlX3NleGVzJHNleAoKIyMgYWRkIHRoaXMgdG8gdGhlIHNldXJhdCBvYmplY3QKcm93bmFtZXMoZGZfbW9ub2NsZV9zZXhlcykgPC0gZGZfbW9ub2NsZV9zZXhlcyRjZWxsX25hbWUKZGZfbW9ub2NsZV9zZXhlc190b19hZGRfdG9fc2V1cmF0IDwtIGRmX21vbm9jbGVfc2V4ZXNbLGMoInNleCIpLCBkcm9wID0gRkFMU0VdCnRlbnguanVzdHd0LmludGVncmF0ZWQgPC0gQWRkTWV0YURhdGEodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGZfbW9ub2NsZV9zZXhlc190b19hZGRfdG9fc2V1cmF0LCBjb2wubmFtZSA9ICJtb25vY2xlX3NleCIpCmBgYAoKcHQgdnMuIHJlYWwgdGltZQpgYGB7cn0KbGlicmFyeShnZ3JpZGdlcykKCmRmX3Bsb3R0aW5nIDwtIGFzLmRhdGEuZnJhbWUodGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEpCgpwdF9yZWFsX3Bsb3QgPC0gZ2dwbG90KGRmX3Bsb3R0aW5nLCBhZXMoeCA9IG9sZF9wdF92YWx1ZXMsIHkgPSAgYXMuZmFjdG9yKFByZWRpY3Rpb24uU3BlYXJtYW4uKSwgZmlsbCA9IGFzLmZhY3RvcihQcmVkaWN0aW9uLlNwZWFybWFuLikpKSArCiAgZ2VvbV9kZW5zaXR5X3JpZGdlcyhhbHBoYSA9IC4xLAogICAgICAgICAgICAgICAgICAgICAgcmVsX21pbl9oZWlnaHQgPSAwLjAzLCAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBxdWFudGlsZV9saW5lcyA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXVhbnRpbGVzID0gMiwKICAgICAgICAgICAgICAgICAgICAgIHNjYWxlID0gMikgKyAjIHBsb3QgcmlnZGVsaW5lcyB3aXRob3V0IHBvaW50cwogICMgcGxvdCBwb2ludHMgd2l0aCBpbnZpc2libGUgcmlkZ2VsaW5lcwogIGdlb21fZGVuc2l0eV9yaWRnZXNfZ3JhZGllbnQocG9pbnRfYWxwaGEgPSAxLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXJlZF9wb2ludHMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHBvaW50X2NvbG9yID0gbW9ub2NsZV9zZXgpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICArCiAgdGhlbWVfY2xhc3NpYygpICsKICBzY2FsZV95X2Rpc2NyZXRlKGRyb3A9RkFMU0UpICsKICBsYWJzKHRpdGxlID0gJycsIHggPSAiUHNldWRvdGltZSIsIHkgPSAiUHJlZGljdGVkIFJlYWwtdGltZSAoaHBpKSIpICsKICAjc2NhbGVfZmlsbF92aXJpZGlzX2MobmFtZSA9ICJwc2V1ZG90aW1lIiwgb3B0aW9uID0gIkMiLCBhbHBoYSA9IDEpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2xpbmUoc2l6ZSA9ICgwLjIpLCBjb2xvdXI9ImdyZXkiKQogICAgICAgICkKCnB0X3JlYWxfcGxvdApgYGAKCmBgYHtyfQpnZyA8LSBnZ3Bsb3QoZGZfcGxvdHRpbmcsIGFlcyhhcy5mYWN0b3IoUHJlZGljdGlvbi5TcGVhcm1hbi4pLCBmaWxsID0gbW9ub2NsZV9zZXgpKSArIGdlb21fYmFyKHN0YXQgPSAiY291bnQiLCBwb3NpdGlvbj0iZmlsbCIpCgpnZwpgYGAKCgojIDguIFBsb3RzIHsudGFic2V0fQoKbWFrZSBjb21wb3NpdGUgcHNldWRvdGltZS9JRCBmaWd1cmUKCmBgYHtyfQojIDEgPSBibHVlIC0gIiMwMDUyYzUiCiMgMiA9IHJlZCAtICIjYTUyYjFlIgojIDMgPSBncmVlbiAtICIjMDE2YzAwIgojIDQgPSB5ZWxsb3cgLSAiI2ZmZTQwMCIKI3BhbF9zZXggPC0gYygiIzAwNTJjNSIsIiNmZmU0MDAiLCAiI2E1MmIxZSIsICIjMDE2YzAwIikKCiMjIGV4dHJhY3QgcHNldWRvdGltZSBudW1iZXJzIGFuZCBpZGVudGl0eSBvZiBjZWxscyB0byBhIGRhdGFmcmFtZQpkZl9wdF9pZCA8LSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YVssYygib2xkX3B0X3ZhbHVlcyIsICJtb25vY2xlX3NleCIpXQoKIyMgaW5zcGVjdCBwb3NzaWJsZSB2YWx1ZXMKbGlzdF9vZl9zZXhlcyA8LSBuYW1lcyh0YWJsZShkZl9wdF9pZCRtb25vY2xlX3NleCkpCgojIyBtYWtlIGEgbmV3IGNvbHVtbgpkZl9wdF9pZCRjb2xvdXIgPC0gTkEKCiMjIG1ha2UgY29sb3VyIHJhbXBzCmFzZXhfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoIiNENUUzRjUiLCAiIzAwNTJjNSIpKQptYWxlX3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJ3aGl0ZSIsICJ5ZWxsb3ciLCAiIzAxNmMwMCIpKQpmZW1hbGVfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoInllbGxvdyIsICIjYTUyYjFlIikpCmJpcG90X3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJ3aGl0ZSIsICIjZmZlNDAwIikpCgojIyByZS1jbGFzc2lmeSB0aGUgY2VsbHMgdGhhdCBhcmUgdW5hc3NpZ25lZCBjZWxscyByZW1vdmVkIGZyb20gc2V4dWFsIGJyYW5jaCBhYm92ZToKI2RmX3B0X2lkW3doaWNoKHJvd25hbWVzKGRmX3B0X2lkKSAlaW4lIHJlbW92ZV9jZWxscyksIF0kbW9ub2NsZV9zZXggPC0gIkFzZXh1YWwiCgojIyBhc3NpZ24gdmFsdWVzIHRvIGVhY2ggY2x1c3RlcgojIyBoZWxwIGhlcmU6IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzk5NDY2MzAvY29sb3VyLXBvaW50cy1pbi1hLXBsb3QtZGlmZmVyZW50bHktZGVwZW5kaW5nLW9uLWEtdmVjdG9yLW9mLXZhbHVlcyAKZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfRWFybHkiIHwgZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfTGF0ZSIsIF0kY29sb3VyIDwtIGFzZXhfcmFtcCgxMDApW2FzLm51bWVyaWMoY3V0KGRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJBc2V4dWFsX0Vhcmx5IiB8IGRmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJBc2V4dWFsX0xhdGUiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSldCgpkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiTWFsZSIsIF0kY29sb3VyIDwtIG1hbGVfcmFtcCgxMDApW2FzLm51bWVyaWMoY3V0KGRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJNYWxlIiwgXSRvbGRfcHRfdmFsdWVzLGJyZWFrcyA9IDEwMCkpXQoKZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkZlbWFsZSIsIF0kY29sb3VyIDwtIGZlbWFsZV9yYW1wKDEwMClbYXMubnVtZXJpYyhjdXQoZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkZlbWFsZSIsIF0kb2xkX3B0X3ZhbHVlcyxicmVha3MgPSAxMDApKV0KCmRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJCaXBvdGVudGlhbCIsIF0kY29sb3VyIDwtIGJpcG90X3JhbXAoMTAwKVthcy5udW1lcmljKGN1dChkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQmlwb3RlbnRpYWwiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSldCgojIyBjaGVjayBldmVyeXRoaW5nIGhhcyBhIHZhbHVlCiN0YWJsZShpcy5uYShkZl9wdF9pZCRjb2xvdXIpKQoKIyMgbWFrZSBpbnRvIGEgZGYKI2RmX3B0X2lkIDwtIGRmX3B0X2lkWyAsImNvbG91ciIsIGRyb3AgPSBGQUxTRV0KCiMjIGFkZCBiYWNrIHRvIHNldXJhdCBvYmplY3QKZGYgPC0gZGZfcHRfaWRbICwiY29sb3VyIiwgZHJvcCA9IEZBTFNFXQp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIEFkZE1ldGFEYXRhKHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRmLCAicHRfaWRfY29scyIpCnJtKGRmKQoKIyMgcGxvdAojIyBleHRyYWN0IFVNQVAgY29vcmRzCmRmX3VtYXBfcGxvdCA8LSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQHJlZHVjdGlvbnNbWyJ1bWFwIl1dQGNlbGwuZW1iZWRkaW5ncwpkZl91bWFwX3Bsb3QgPC0gbWVyZ2UoZGZfdW1hcF9wbG90LCBkZl9wdF9pZCwgYnk9MCwgYWxsPVRSVUUpCgojIyBhZGQgdHJlZQojI1RoZSB0cmVlIGZvciBtb25vY2xlIGlzIGxvY2F0ZWQgaGVyZToKIyBtb25vY2xlLm9iamVjdEBwcmluY2lwYWxfZ3JhcGhfYXV4W1siVU1BUCJdXSRkcF9tc3QgCmljYV9zcGFjZV9kZiA8LSB0KG1vbm9jbGUub2JqZWN0LmFsbEBwcmluY2lwYWxfZ3JhcGhfYXV4W1siVU1BUCJdXSRkcF9tc3QpICU+JQogICAgICBhcy5kYXRhLmZyYW1lKCkgJT4lCiAgICAgIGRwbHlyOjpzZWxlY3RfKHByaW5fZ3JhcGhfZGltXzEgPSAiVU1BUF8xIiwgcHJpbl9ncmFwaF9kaW1fMiA9ICJVTUFQXzIiKSAlPiUKICAgICAgZHBseXI6Om11dGF0ZShzYW1wbGVfbmFtZSA9IHJvd25hbWVzKC4pLAogICAgICAgICAgICAgICAgICAgIHNhbXBsZV9zdGF0ZSA9IHJvd25hbWVzKC4pKQoKZHBfbXN0IDwtIG1vbm9jbGUub2JqZWN0LmFsbEBwcmluY2lwYWxfZ3JhcGhbWyJVTUFQIl1dCgplZGdlX2RmIDwtIGRwX21zdCAlPiUKICAgICAgaWdyYXBoOjphc19kYXRhX2ZyYW1lKCkgJT4lCiAgICAgIGRwbHlyOjpzZWxlY3RfKHNvdXJjZSA9ICJmcm9tIiwgdGFyZ2V0ID0gInRvIikgJT4lCiAgICAgIGRwbHlyOjpsZWZ0X2pvaW4oaWNhX3NwYWNlX2RmICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdF8oCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZT0ic2FtcGxlX25hbWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VfcHJpbl9ncmFwaF9kaW1fMT0icHJpbl9ncmFwaF9kaW1fMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZV9wcmluX2dyYXBoX2RpbV8yPSJwcmluX2dyYXBoX2RpbV8yIiksCiAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAic291cmNlIikgJT4lCiAgICAgIGRwbHlyOjpsZWZ0X2pvaW4oaWNhX3NwYWNlX2RmICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdF8oCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldD0ic2FtcGxlX25hbWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXRfcHJpbl9ncmFwaF9kaW1fMT0icHJpbl9ncmFwaF9kaW1fMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldF9wcmluX2dyYXBoX2RpbV8yPSJwcmluX2dyYXBoX2RpbV8yIiksCiAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAidGFyZ2V0IikKCiMjIG1ha2UgZ2dwbG90CnVtYXBfaWRfcHQgPC0gZ2dwbG90KGRmX3VtYXBfcGxvdCwgYWVzKHggPSBVTUFQXzEsIHkgPSBVTUFQXzIpKSArIAogICAgICAgICAgICAgICAgICAgICBnZW9tX3BvaW50KGNvbCA9IGRmX3VtYXBfcGxvdCRjb2xvdXIpICsKICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsKICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArCiAgICAgICAgICAgICAgICAgICAgIGdlb21fc2VnbWVudChhZXNfc3RyaW5nKHg9InNvdXJjZV9wcmluX2dyYXBoX2RpbV8xIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9InNvdXJjZV9wcmluX2dyYXBoX2RpbV8yIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhlbmQ9InRhcmdldF9wcmluX2dyYXBoX2RpbV8xIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHllbmQ9InRhcmdldF9wcmluX2dyYXBoX2RpbV8yIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YT1lZGdlX2RmKQoKdW1hcF9pZF9wdApgYGAKCnNhdmUKYGBge3J9CiNnZ3NhdmUoIi4uL2ltYWdlc190b19leHBvcnQvdW1hcF9pZF9wdC5wbmciLCBwbG90ID0gdW1hcF9pZF9wdCwgZGV2aWNlID0gInBuZyIsIHBhdGggPSBOVUxMLCBzY2FsZSA9IDEsIHdpZHRoID0gMjEsIGhlaWdodCA9IDI5LjcsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKY2x1c3RlciBwbG90CmBgYHtyfQojIyMgUHJlcGFyZSBkYXRhCgojIyBleHRyYWN0IGRmIHdpdGggY2x1c3RlciBJRCwgCmRmX3B0X2lkIDwtIHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhWyAsInNldXJhdF9jbHVzdGVycyIsIGRyb3A9RkFMU0VdCiMjIGV4dHJhY3QgVU1BUCBjb29yZHMKZGZfcGxvdCA8LSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQHJlZHVjdGlvbnNbWyJ1bWFwIl1dQGNlbGwuZW1iZWRkaW5ncwpkZl9wbG90IDwtIG1lcmdlKGRmX3Bsb3QsIGRmX3B0X2lkLCBieT0wLCBhbGw9VFJVRSkKIyMgYWRkIGNvbG91ciBjb2wKZGZfcGxvdCRjb2xvdXIgPC0gZGZfcGxvdCRzZXVyYXRfY2x1c3RlcnMKbGV2ZWxzKGRmX3Bsb3QkY29sb3VyKSA8LSBsaXN0KHByaW50KGFzZXhfcmFtcCgxNylbMV0pID0gIjkiLCBhc2V4X3JhbXAoMTcpWzJdPSI0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzNdPSIxNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbNF0gPSAiOCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbNV09ICIxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzZdPSAgIjE0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVs3XSA9ICIyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVs4XSA9ICIxMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVs5XSA9ICIzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzEwXSA9ICIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzExXSA9ICI2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzEyXSA9ICI1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzEzXSA9ICI3IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzE0XSA9ICIxMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVsxNV0gPSAiMTgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbMTZdID0gIjIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzE3XSA9ICIyMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmlwb3RfcmFtcCgzKVsyXSA9ICIxMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFsZV9yYW1wKDMpWzJdID0gIjE2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYWxlX3JhbXAoMylbM10gPSAiMTMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlbWFsZV9yYW1wKDQpWzJdID0gIjIxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZW1hbGVfcmFtcCg0KVszXSA9ICIyMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVtYWxlX3JhbXAoNClbNF0gPSAiMTkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlbWFsZV9yYW1wKDQpWzRdID0gIjE3IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKIyMgYWFiYnJldmlhdGUgY2x1c3RlcnMKZGZfcGxvdCRjbHVzdGVyX25hbWVzIDwtIGRmX3Bsb3Qkc2V1cmF0X2NsdXN0ZXJzCmxldmVscyhkZl9wbG90JGNsdXN0ZXJfbmFtZXMpIDwtIGxpc3QoQV8xPSI5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8yPSI0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8zPSIxNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfNCA9ICI4IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV81ID0gIjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfNj0gICIxNCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfNyA9ICIyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV84ID0gIjEwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzkgPSAiMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xMCA9ICIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzExID0gIjYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTIgPSAiNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xMyA9ICI3IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzE0ID0gIjEyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzE1ID0gIjE4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzE2ID0gIjIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzE3ID0gIjIzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCID0gIjExIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNXzEgPSAiMTYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1fMiA9ICIxMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRl8xID0gIjIxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGXzIgPSAiMjIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZfMyA9ICIxOSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRl8zID0gIjE3IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKCmxpYnJhcnkoZHBseXIpCmRhdCU+JQpncm91cF9ieShjdXN0aWQpJT4lIApzdW1tYXJpc2UoTWVhbj1tZWFuKHZhbHVlKSwgTWF4PW1heCh2YWx1ZSksIE1pbj1taW4odmFsdWUpLCBNZWRpYW49bWVkaWFuKHZhbHVlKSwgU3RkPXNkKHZhbHVlKSkKCgoKIyMgcGxvdAp1bWFwX2lkIDwtIGdncGxvdChkZl9wbG90LCBhZXMoeCA9IFVNQVBfMSwgeSA9IFVNQVBfMikpICsgCiAgICAgICAgICAgICAgICAgICAgIGdlb21fcG9pbnQoY29sID0gZGZfcGxvdCRjb2xvdXIpICsKICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsKICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKQoKdW1hcF9pZApgYGAKCmBgYHtyfQojIyB0aGVzZSBnZXQgZGVmaW5lZCBsYXRlciBvbiwgYnV0IGFyZSByZXBsaWNhdGVkIGFib3ZlIGhlcmUgZm9yIHBsb3R0aW5nCmFzZXh1YWxfZWFybHlfY2x1c3RlcnMgPC0gYyg5LCA0LCAxNSwgOCwgMSwgMTQsIDIsIDEwLCAzLCAwLCA2LCA1KQphc2V4dWFsX2xhdGVfY2x1c3RlcnMgPC0gYyg3LCAxMiwgMTgsIDIwLCAyMykKYmlwb3RlbnRpb25hbF9lYXJseV9jbHVzdGVycyA8LSAjIDA/CmJpcG90ZW50aWFsX2NsdXN0ZXJzIDwtIGMoMTEpIAptYWxlX2NsdXN0ZXJzIDwtIGMoMTYsIDEzKQpmZW1hbGVfY2x1c3RlcnMgPC0gYygyMSwgMjIsIDE3LCAxOSkKCiMjIG1ha2UgYSBuZXcgY29sdW1uIGZvciBwbG90dGluZwp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nIDwtIHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVycwoKIyMgcmVvcmRlciB0aGUgbGV2ZWxzIHNvIHlvdSBjYW4gcGxvdCB0aGUgY2x1dGVycyBhcyB5b3Ugd2lzaApteV9sZXZlbHMgPC0gYyhhc2V4dWFsX2Vhcmx5X2NsdXN0ZXJzLGFzZXh1YWxfbGF0ZV9jbHVzdGVycywgYmlwb3RlbnRpYWxfY2x1c3RlcnMsIG1hbGVfY2x1c3RlcnMsIGZlbWFsZV9jbHVzdGVycykKdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyA8LSBmYWN0b3IoeCA9IHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcsIGxldmVscyA9IG15X2xldmVscykKCiMjIGNoYW5nZSB0aGUgbGV2ZWxzCmxldmVscyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nKSA8LSBsaXN0KEFfMT0iOSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMj0iNCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMz0iMTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzQgPSAiOCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfNSA9ICIxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzY9ICAiMTQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzcgPSAiMiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfOCA9ICIxMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV85ID0gIjMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTAgPSAiMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xMSA9ICI2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzEyID0gIjUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTMgPSAiNyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xNCA9ICIxMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xNSA9ICIxOCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xNiA9ICIyMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xNyA9ICIyMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUCA9ICIxMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTV8xID0gIjE2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNXzIgPSAiMTMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZfMSA9ICIyMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRl8yID0gIjIyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGXzMgPSAiMTkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZfMyA9ICIxNyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCgojIyMgQW5ub3RhdGlvbiBzZXQtdXAKCiMjIGV4dHJhY3QgcHNldWRvdGltZSBudW1iZXJzIGFuZCBpZGVudGl0eSBvZiBjZWxscyB0byBhIGRhdGFmcmFtZQpkZl9wdF9pZCA8LSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YVssYygib2xkX3B0X3ZhbHVlcyIsICJtb25vY2xlX3NleCIsICJzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nIiwgIlByZWRpY3Rpb24uU3BlYXJtYW4uIiwgIlByZWRpY3Rpb24uU3BlYXJtYW4uX0thc2lhIildCgojIyBtYWtlIGEgbmV3IGNvbHVtbgpkZl9wdF9pZCRjb2xvdXIgPC0gTkEKCiMjIGFzc2lnbiBiaW5zIHRvIGVhY2ggb2YgdGhlIHZhbHVlcwojIyBoZWxwIGhlcmU6IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzk5NDY2MzAvY29sb3VyLXBvaW50cy1pbi1hLXBsb3QtZGlmZmVyZW50bHktZGVwZW5kaW5nLW9uLWEtdmVjdG9yLW9mLXZhbHVlcyAKZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfRWFybHkiIHwgZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfTGF0ZSIsIF0kY29sb3VyIDwtIGFzLm51bWVyaWMoY3V0KGRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJBc2V4dWFsX0Vhcmx5IiB8IGRmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJBc2V4dWFsX0xhdGUiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSkKCmRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJNYWxlIiwgXSRjb2xvdXIgPC0gYXMubnVtZXJpYyhjdXQoZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIk1hbGUiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSkKCmRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJGZW1hbGUiLCBdJGNvbG91ciA8LSBhcy5udW1lcmljKGN1dChkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiRmVtYWxlIiwgXSRvbGRfcHRfdmFsdWVzLGJyZWFrcyA9IDEwMCkpCgpkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQmlwb3RlbnRpYWwiLCBdJGNvbG91ciA8LSBhcy5udW1lcmljKGN1dChkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQmlwb3RlbnRpYWwiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSkKCiMjIG1ha2UgY29sb3VyIHJhbXBzCmFzZXhfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoIiNENUUzRjUiLCAiIzAwNTJjNSIpKQptYWxlX3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJ3aGl0ZSIsICJ5ZWxsb3ciLCAiIzAxNmMwMCIpKQpmZW1hbGVfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoInllbGxvdyIsICIjYTUyYjFlIikpCmJpcG90X3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJ3aGl0ZSIsICIjZmZlNDAwIikpCgojIyBhc3NpZ24gdmFsdWVzIHRvIGVhY2ggY2x1c3RlcgojIyB0YWtlIHRoZSBtZWFuIG9mIHRoZSBiaW4KZGZfYW5ub3RhdGlvbiA8LSBhZ2dyZWdhdGUoZGZfcHRfaWRbLCAiY29sb3VyIl0sIGxpc3QoZGZfcHRfaWQkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyksIG1lYW4pCiMjIEJFQ0FVU0Ugd2UgaGF2ZSBvcmRlcmVkIHRoZSBjbHVzdGVycyBhbHJlYWR5LCB3ZSBjYW4gc2ltcGx5IHRha2UgdGhlIHJvdyBpbmRleCBmb3IgdGhpcyBiaXQKZGZfYW5ub3RhdGlvbiRjb2xvdXIgPC0gTkEKZGZfYW5ub3RhdGlvblsxOjE3LCBdJGNvbG91ciA8LSBhc2V4X3JhbXAoMTAwKVtkZl9hbm5vdGF0aW9uWzE6MTcsIF0keF0KZGZfYW5ub3RhdGlvblsxOCwgXSRjb2xvdXIgPC0gYmlwb3RfcmFtcCgxMDApW2RmX2Fubm90YXRpb25bMTgsIF0keF0KZGZfYW5ub3RhdGlvblsxOToyMCwgXSRjb2xvdXIgPC0gbWFsZV9yYW1wKDEwMClbZGZfYW5ub3RhdGlvblsxOToyMCwgXSR4XQpkZl9hbm5vdGF0aW9uWzIxOjIzLCBdJGNvbG91ciA8LSBmZW1hbGVfcmFtcCgxMDApW2RmX2Fubm90YXRpb25bMjE6MjMsIF0keF0KCiMjIG1ha2UgY29sb3VyIHBhbGxldGUKI3BhbF9wbG90IDwtIGMoYXNleF9yYW1wKDE3MClbMSwxMSwyMSwzMSxdLCBiaXBvdF9yYW1wKDMpWzJdLCBtYWxlX3JhbXAoNSlbMzo0XSwgZmVtYWxlX3JhbXAoNSlbMjo1XSkKcGFsX3Bsb3QgPC0gYyhkZl9hbm5vdGF0aW9uJGNvbG91ciwgJyM0OUMxNkRGRicpCgojIyBwbG90CnVtYXBfd2l0aF9jbHVzdGVycyA8LSBEaW1QbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsCiAgICAgICAgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyIsCiAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICBwdC5zaXplID0gMSwKICAgICAgICBsYWJlbC5ib3ggPSBUUlVFLAogICAgICAgIGxhYmVsLnNpemUgPSA4LAogICAgICAgIGxhYmVsLmNvbG9yCT0gYyhyZXAoYygiIzAwMDAwMCIpLCAxMiksIHJlcChjKCIjZmZmZmZmIiksIDUpLCByZXAoYygiIzAwMDAwMCIpLCAyKSwiI2ZmZmZmZiIsICIjMDAwMDAwIiwgIiNmZmZmZmYiLCAiI2ZmZmZmZiIpLAogICAgICAgIG9yZGVyID0gVFJVRSwgCiAgICAgICAgcmVwZWwgPSBUUlVFLCAKICAgICAgICBsYWJlbCA9IFRSVUUsCiAgICAgICAgY29scyA9IHBhbF9wbG90KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKGxhYmVscyA9IGMoIkFzZXh1YWwgMSIsICJBc2V4dWFsIDIiICwgIkFzZXh1YWwgMyIsICJBc2V4dWFsIDQiLCAiQXNleHVhbCA1IiwgIkFzZXh1YWwgNiIsICJBc2V4dWFsIDciLCAiQXNleHVhbCA4IiwgICJBc2V4dWFsIDkiLCAiQXNleHVhbCAxMCIsICJBc2V4dWFsIDExIiwgIkFzZXh1YWwgMTIiLCAiQXNleHVhbCAxMyIsICJBc2V4dWFsIDE0IiwgIkFzZXh1YWwgMTUiLCAiQXNleHVhbCAxNiIsICJBc2V4dWFsIDE3IiwgIlByb2dlbml0b3IiLCAiTWFsZSAxIiwgIk1hbGUgMiIsICJGZW1hbGUgMSIsICJGZW1hbGUgMiIsICJGZW1hbGUgMyIpLCB2YWx1ZXMgPSBwYWxfcGxvdCkgKwogIHRoZW1lX3ZvaWQoKSArCiAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkKCnVtYXBfd2l0aF9jbHVzdGVycwpgYGAKCnNhdmUKYGBge3J9Cmdnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC91bWFwX3dpdGhfY2x1c3RlcnMucG5nIiwgcGxvdCA9IHVtYXBfd2l0aF9jbHVzdGVycywgZGV2aWNlID0gInBuZyIsIHBhdGggPSBOVUxMLCBzY2FsZSA9IDEsIHdpZHRoID0gMjEsIGhlaWdodCA9IDI5LjUsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKCiMjIyBkb3RwbG90CgpBIGRvdHBsb3QgYWxsb3dzIHVzIHRvIGxvb2sgYXQgdGhlIGV4cHJlc3Npb24gb2YgbXVsdGlwbGUgZ2VuZXMgaW4gYSBjbGVhcmVyIHdheSB0aGFuIHN1Y2Nlc2l2ZSBVTUFQIHBsb3RzCgpgYGB7ciwgZmlnLndpZHRoID0gOSwgZmlnLmhlaWdodD0gOH0KIyMjIERhdGEgc2V0LXVwCgojIFBCQU5LQS0wODI4MDAwICAgICAgICAgR0NTS08tMyAgR0QxCgojIFBCQU5LQS0xMzAyNzAwICAgICAgIEdDU0tPLW9vbSAgTUQxIAojIFBCQU5LQS0xNDQ3OTAwICAgICAgICBHQ1NLTy0yOSAgTUQyCiMgUEJBTktBLTA0MTM0MDAgICAgR0NTS08tMTBfODIwICBNRDMKIyBQQkFOS0EtMDcxNjUwMCAgICAgICAgR0NTS08tMTkgIE1ENCAKIyBQQkFOS0EtMDEwMjQwMCAgICAgICAgIEdDU0tPLTIgIE1ENSAKCiMgUEJBTktBLTE0NTQ4MDAgICAgICAgIEdDU0tPLTIxICBGRDEKIyBQQkFOS0EtMDkwMjMwMCAgICAgICAgR0NTS08tMTMgIEZEMgojIFBCQU5LQS0xNDE4MTAwICAgICAgICBHQ1NLTy0xNyAgRkQzICAgCiMgUEJBTktBLTE0MzUyMDAgICAgICAgIEdDU0tPLTIwICBGRDQgCgojIFBCQU5LQS0xNDM3NTAwIC0gQVAyRyAtIGNvbW1pdG1lbnQKIyBQQkFOS0EtMTMxOTUwMCAtIENDUDIgLSBmZW1hbGUgLSB1c2VkIGluIDgyMCBsaW5lCiMgUEJBTktBLTA0MTYxMDAgLSBNRzEgLSBkeW5lbmluIGhlYXZ5IGNoYWluIC0gbWFsZSAtIHVzZWQgaW4gODIwIGxpbmUKIyBQQkFOS0EtMDgzMTAwMCAtIE1TUDEgLSBsYXRlIGFzZXh1YWwKIyBQQkFOS0EtMTEwMjIwMCAtIE1TUDggLSBlYXJseSBhc2V4dWFsIChmcm9tIEJvemRlY2ggcGFwZXIpCgptYXJrZXJfZ2VuZXNfbGlzdCA8LSBjKCJQQkFOS0EtMTQzNzUwMCIsICJQQkFOS0EtMTMxOTUwMCIsICJQQkFOS0EtMDQxNjEwMCIsICJQQkFOS0EtMDgzMTAwMCIsICJQQkFOS0EtMTEwMjIwMCIpCm11dGFudF9nZW5lc19saXN0IDwtIGMoIlBCQU5LQS0wODI4MDAwIiwgIlBCQU5LQS0xMzAyNzAwIiwgIlBCQU5LQS0xNDQ3OTAwIiwgIlBCQU5LQS0wNDEzNDAwIiwgIlBCQU5LQS0wNzE2NTAwIiwgIlBCQU5LQS0wMTAyNDAwIiwgICJQQkFOS0EtMTQ1NDgwMCIsICJQQkFOS0EtMDkwMjMwMCIsICJQQkFOS0EtMTQxODEwMCIsICJQQkFOS0EtMTQzNTIwMCIpCgojIyB0aGVzZSBnZXQgZGVmaW5lZCBsYXRlciBvbiwgYnV0IGFyZSByZXBsaWNhdGVkIGFib3ZlIGhlcmUgZm9yIHBsb3R0aW5nCmFzZXh1YWxfZWFybHlfY2x1c3RlcnMgPC0gYyg5LCA0LCAxNSwgOCwgMSwgMTQsIDIsIDEwLCAzLCAwLCA2LCA1KQphc2V4dWFsX2xhdGVfY2x1c3RlcnMgPC0gYyg3LCAxMiwgMTgsIDIwLCAyMykKYmlwb3RlbnRpb25hbF9lYXJseV9jbHVzdGVycyA8LSAjIDA/CmJpcG90ZW50aWFsX2NsdXN0ZXJzIDwtIGMoMTEpIAptYWxlX2NsdXN0ZXJzIDwtIGMoMTYsIDEzKQpmZW1hbGVfY2x1c3RlcnMgPC0gYygyMSwgMjIsIDE3LCAxOSkKCiMjIGNvcHkgdGhlIGNsdXN0ZXJzIHNvIHlvdSBkb24ndCBwZXJtYW5lbnRseSBlZGl0IHRoZSBtYXN0ZXIKdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyA8LSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnMKCiMjIHJlb3JkZXIgdGhlIGxldmVscyBzbyB5b3UgY2FuIHBsb3QgdGhlIGNsdXRlcnMgYXMgeW91IHdpc2gKbXlfbGV2ZWxzIDwtIGMoYXNleHVhbF9lYXJseV9jbHVzdGVycyxhc2V4dWFsX2xhdGVfY2x1c3RlcnMsIGJpcG90ZW50aWFsX2NsdXN0ZXJzLCBtYWxlX2NsdXN0ZXJzLCBmZW1hbGVfY2x1c3RlcnMpCgojIyByZW9yZGVyIHRoZSBsZXZlbHMKdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyA8LSBmYWN0b3IoeCA9IHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcsIGxldmVscyA9IG15X2xldmVscykKCiMjIHJlbmFtZSBjbHVzdGVycyBzbyB0aGF0IHRoZXkgYXJlIGludHVpdGl2ZQojIHRoaXMgdHJpY2sgaXMgZnJvbSBoZXJlOiBodHRwOi8vd3d3LmNvb2tib29rLXIuY29tL01hbmlwdWxhdGluZ19kYXRhL1JlbmFtaW5nX2xldmVsc19vZl9hX2ZhY3Rvci8KbGV2ZWxzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcpIDwtIGxpc3QoQXNleHVhbF8xPSI5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfMj0iNCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzM9IjE1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfNCA9ICI4IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfNSA9ICIxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF82PSAgIjE0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfNyA9ICIyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfOCA9ICIxMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfOSA9ICIzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF8xMCA9ICIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF8xMSA9ICI2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF8xMiA9ICI1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF8xMyA9ICI3IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF8xNCA9ICIxMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfMTUgPSAiMTgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzE2ID0gIjIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF8xNyA9ICIyMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJpcG90ZW50aWFsID0gIjExIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWFsZV8xID0gIjE2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWFsZV8yID0gIjEzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRmVtYWxlXzEgPSAiMjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGZW1hbGVfMiA9ICIyMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZlbWFsZV8zID0gIjE5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRmVtYWxlXzMgPSAiMTciCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKCiMjIyBBbm5vdGF0aW9uIHNldC11cAoKIyMgZXh0cmFjdCBwc2V1ZG90aW1lIG51bWJlcnMgYW5kIGlkZW50aXR5IG9mIGNlbGxzIHRvIGEgZGF0YWZyYW1lCmRmX3B0X2lkIDwtIHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhWyxjKCJvbGRfcHRfdmFsdWVzIiwgIm1vbm9jbGVfc2V4IiwgInNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmciLCAiUHJlZGljdGlvbi5TcGVhcm1hbi4iLCAiUHJlZGljdGlvbi5TcGVhcm1hbi5fS2FzaWEiKV0KCiMjIG1ha2UgYSBuZXcgY29sdW1uCmRmX3B0X2lkJGNvbG91ciA8LSBOQQoKIyMgYXNzaWduIGJpbnMgdG8gZWFjaCBvZiB0aGUgdmFsdWVzCiMjIGhlbHAgaGVyZTogaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvOTk0NjYzMC9jb2xvdXItcG9pbnRzLWluLWEtcGxvdC1kaWZmZXJlbnRseS1kZXBlbmRpbmctb24tYS12ZWN0b3Itb2YtdmFsdWVzIApkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQXNleHVhbF9FYXJseSIgfCBkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQXNleHVhbF9MYXRlIiwgXSRjb2xvdXIgPC0gYXMubnVtZXJpYyhjdXQoZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfRWFybHkiIHwgZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfTGF0ZSIsIF0kb2xkX3B0X3ZhbHVlcyxicmVha3MgPSAxMDApKQoKZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIk1hbGUiLCBdJGNvbG91ciA8LSBhcy5udW1lcmljKGN1dChkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiTWFsZSIsIF0kb2xkX3B0X3ZhbHVlcyxicmVha3MgPSAxMDApKQoKZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkZlbWFsZSIsIF0kY29sb3VyIDwtIGFzLm51bWVyaWMoY3V0KGRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJGZW1hbGUiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSkKCmRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJCaXBvdGVudGlhbCIsIF0kY29sb3VyIDwtIGFzLm51bWVyaWMoY3V0KGRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJCaXBvdGVudGlhbCIsIF0kb2xkX3B0X3ZhbHVlcyxicmVha3MgPSAxMDApKQoKIyMgbWFrZSBjb2xvdXIgcmFtcHMKYXNleF9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygiI0Q1RTNGNSIsICIjMDA1MmM1IikpCm1hbGVfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoIndoaXRlIiwgInllbGxvdyIsICIjMDE2YzAwIikpCmZlbWFsZV9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygieWVsbG93IiwgIiNhNTJiMWUiKSkKYmlwb3RfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoIndoaXRlIiwgIiNmZmU0MDAiKSkKCiMjIGFzc2lnbiB2YWx1ZXMgdG8gZWFjaCBjbHVzdGVyCiMjIHRha2UgdGhlIG1lYW4gb2YgdGhlIGJpbgpkZl9hbm5vdGF0aW9uIDwtIGFnZ3JlZ2F0ZShkZl9wdF9pZFssICJjb2xvdXIiXSwgbGlzdChkZl9wdF9pZCRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nKSwgbWVhbikKIyMgQkVDQVVTRSB3ZSBoYXZlIG9yZGVyZWQgdGhlIGNsdXN0ZXJzIGFscmVhZHksIHdlIGNhbiBzaW1wbHkgdGFrZSB0aGUgcm93IGluZGV4IGZvciB0aGlzIGJpdApkZl9hbm5vdGF0aW9uJGNvbG91ciA8LSBOQQpkZl9hbm5vdGF0aW9uWzE6MTcsIF0kY29sb3VyIDwtIGFzZXhfcmFtcCgxMDApW2RmX2Fubm90YXRpb25bMToxNywgXSR4XQpkZl9hbm5vdGF0aW9uWzE4LCBdJGNvbG91ciA8LSBiaXBvdF9yYW1wKDEwMClbZGZfYW5ub3RhdGlvblsxOCwgXSR4XQpkZl9hbm5vdGF0aW9uWzE5OjIwLCBdJGNvbG91ciA8LSBtYWxlX3JhbXAoMTAwKVtkZl9hbm5vdGF0aW9uWzE5OjIwLCBdJHhdCmRmX2Fubm90YXRpb25bMjE6MjMsIF0kY29sb3VyIDwtIGZlbWFsZV9yYW1wKDEwMClbZGZfYW5ub3RhdGlvblsyMToyMywgXSR4XQoKIyMgcGxvdCBhbm5vdGF0aW9uIAojIyB0aGlzIHJlYWxseSBoZWxwZWQ6IGh0dHBzOi8vd3d3LmJpb3N0YXJzLm9yZy9wLzM5NjgxMC8KaDIgPC0gZ2dwbG90KGRmX2Fubm90YXRpb24pKwogIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoeCA9IEdyb3VwLjEsIHkgPSAxKSwgCiAgICAgICAgICAgc3RhdCA9ICJpZGVudGl0eSIsCiAgICAgICAgICAgZmlsbCA9IGRmX2Fubm90YXRpb24kY29sb3VyLAogICAgICAgICAgIGNvbCA9ICIjRkZGRkZGIiwKICAgICAgICAgICB3aWR0aCA9IDEpKwogICAgICB0aGVtZV92b2lkKCkrCiAgICAgIHRoZW1lKHBhbmVsLnNwYWNpbmcueCA9IHVuaXQoMSwgIm1tIikpIysKICAgICAjZmFjZXRfZ3JpZCgufmNvbG91ciwgc2NhbGVzID0gImZyZWVfeCIpCiAgICAgI2xlZ2VuZCA8LSBwbG90X2dyaWQoZ2V0X2xlZ2VuZChoMiksIGdldF9sZWdlbmQoaDEpLCBuY29sID0gMSkKIGgyIDwtIGgyICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQogIyAgIGdlb21fcG9pbnQoY29sID0gZGZfdW1hcF9wbG90JGNvbG91cikKIAogaDEgPC0gZ2dwbG90KGRmX2Fubm90YXRpb24pKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gR3JvdXAuMSwgeSA9IDEpLAogICAgICAgICAgICBjb2wgPSBkZl9hbm5vdGF0aW9uJGNvbG91ciwKICAgICAgICAgICAgc2l6ZSA9IDUpKwogICAgICB0aGVtZV92b2lkKCkrCiAgICAgIHRoZW1lKHBhbmVsLnNwYWNpbmcueCA9IHVuaXQoMSwgIm1tIikpIysKICAgICAjZmFjZXRfZ3JpZCgufmNvbG91ciwgc2NhbGVzID0gImZyZWVfeCIpCiAgICAgI2xlZ2VuZCA8LSBwbG90X2dyaWQoZ2V0X2xlZ2VuZChoMiksIGdldF9sZWdlbmQoaDEpLCBuY29sID0gMSkKIGgxIDwtIGgxICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQogIyAgIGdlb21fcG9pbnQoY29sID0gZGZfdW1hcF9wbG90JGNvbG91cikKCiAjIyBhZGQgcHJlZGljdGVkIHRpbWUgcG9pbnQKICMjIHRha2UgdGhlIG1lYW4gb2YgdGhlIGJpbgpkZl9hbm5vdGF0aW9uIDwtIGFnZ3JlZ2F0ZShkZl9wdF9pZFssICJQcmVkaWN0aW9uLlNwZWFybWFuLiJdLCBsaXN0KGRmX3B0X2lkJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcpLCBtZWFuKQpkZl9hbm5vdGF0aW9uJGNvbG91ciA8LSBOQQpkZl9hbm5vdGF0aW9uJGNvbG91ciA8LSB2aXJpZGlzKDMwMClbKGRmX2Fubm90YXRpb24keCkqMTBdCgpoMyA8LSBnZ3Bsb3QoZGZfYW5ub3RhdGlvbikrCiAgZ2VvbV9iYXIobWFwcGluZyA9IGFlcyh4ID0gR3JvdXAuMSwgeSA9IDEpLCAKICAgICAgICAgICBzdGF0ID0gImlkZW50aXR5IiwKICAgICAgICAgICBmaWxsID0gZGZfYW5ub3RhdGlvbiRjb2xvdXIsCiAgICAgICAgICAgY29sID0gIiNGRkZGRkYiLAogICAgICAgICAgIHdpZHRoID0gMSkrCiAgICAgIHRoZW1lX3ZvaWQoKSsKICAgICAgdGhlbWUocGFuZWwuc3BhY2luZy54ID0gdW5pdCgxLCAibW0iKSkjKwogICAgICNmYWNldF9ncmlkKC5+Y29sb3VyLCBzY2FsZXMgPSAiZnJlZV94IikKICAgICBsZWdlbmRfaDMgPC0gZ2V0X2xlZ2VuZChoMykKIGgzIDwtIGgzICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKICBoMyA8LSBnZ3Bsb3QoZGF0YSA9IGRmX2Fubm90YXRpb24sIAogICAgICAgICAgICAgIG1hcHBpbmcgPSBhZXMoeCA9IEdyb3VwLjEsIGZpbGw9eCkKICAgICAgICAgICAgICApICsKICAgICAgIGdlb21fYmFyKGNvbCA9ICIjRkZGRkZGIiwgd2lkdGggPSAxKSsKICAgICAgIHRoZW1lX3ZvaWQoKSArCiAgICAgICB0aGVtZShwYW5lbC5zcGFjaW5nLnggPSB1bml0KDEsICJtbSIpKSArCiAgICAgICBzY2FsZV9maWxsX3ZpcmlkaXMob3B0aW9uID0gJ2NpdmlkaXMnKQogbGVnZW5kX2gzIDwtIGdldF9sZWdlbmQoaDMpCiBoMyA8LSBoMyArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKIAogIyMgYWRkIGthc2lhIGRhdGEKICAjIyB0YWtlIHRoZSBtZWFuIG9mIHRoZSBiaW4KZGZfYW5ub3RhdGlvbiA8LSBhZ2dyZWdhdGUoZGZfcHRfaWRbLCAiUHJlZGljdGlvbi5TcGVhcm1hbi5fS2FzaWEiXSwgbGlzdChkZl9wdF9pZCRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nKSwgbWVhbikKZGZfYW5ub3RhdGlvbiRjb2xvdXIgPC0gTkEKZGZfYW5ub3RhdGlvbiRjb2xvdXIgPC0gdmlyaWRpcygzMDApWyhkZl9hbm5vdGF0aW9uJHgpKjEwXQoKaDQgPC0gZ2dwbG90KGRmX2Fubm90YXRpb24pKwogIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoeCA9IEdyb3VwLjEsIHkgPSAxKSwgCiAgICAgICAgICAgc3RhdCA9ICJpZGVudGl0eSIsCiAgICAgICAgICAgZmlsbCA9IGRmX2Fubm90YXRpb24kY29sb3VyLAogICAgICAgICAgIGNvbCA9ICIjRkZGRkZGIiwKICAgICAgICAgICB3aWR0aCA9IDEpKwogICAgICB0aGVtZV92b2lkKCkrCiAgICAgIHRoZW1lKHBhbmVsLnNwYWNpbmcueCA9IHVuaXQoMSwgIm1tIikpKwogICAgIGZhY2V0X2dyaWQoLn5jb2xvdXIsIHNjYWxlcyA9ICJmcmVlX3giKQogICAgIGxlZ2VuZCA8LSBwbG90X2dyaWQoZ2V0X2xlZ2VuZChoNCksIG5jb2wgPSAxKQogICAgbGVnZW5kX2g0IDwtIGdldF9sZWdlbmQoaDQpCiBoNCA8LSBoNCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCiBoNCA8LSBnZ3Bsb3QoZGF0YSA9IGRmX2Fubm90YXRpb24sIAogICAgICAgICAgICAgIG1hcHBpbmcgPSBhZXMoeCA9IEdyb3VwLjEsIGZpbGw9eCkKICAgICAgICAgICAgICApICsKICAgICAgIGdlb21fYmFyKGNvbCA9ICIjRkZGRkZGIiwgd2lkdGggPSAxKSsKICAgICAgIHRoZW1lX3ZvaWQoKSArCiAgICAgICB0aGVtZShwYW5lbC5zcGFjaW5nLnggPSB1bml0KDEsICJtbSIpKSArCiAgICAgICBzY2FsZV9maWxsX3ZpcmlkaXMoKQogbGVnZW5kX2g0IDwtIGdldF9sZWdlbmQoaDQpCiBoNCA8LSBoNCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCiMjIyBQbG90CmRvdF9wbG90X21hcmtlcnMgPC0gRG90UGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gYyhtYXJrZXJfZ2VuZXNfbGlzdCwgcmV2KG11dGFudF9nZW5lc19saXN0KSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZG90Lm1pbiA9IDAuMDAwMDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheSA9ICdSTkEnKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICBjb29yZF9maXhlZCgpICsKICBjb29yZF9mbGlwKCkgKwogICMgY2hhbmdlIGFwcGVhcmFuY2UgYW5kIHJlbW92ZSBheGlzIGVsZW1lbnRzLCBhbmQgbWFrZSByb29tIGZvciBhcnJvd3MKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBhbmdsZSA9IDQ1LCBoanVzdD0xLHZqdXN0PTEsIGZhbWlseSA9ICJBcmlhbCIpLCAKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBmYWNlPSJpdGFsaWMiKSwgCiAgICAgICAgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xNiwgZmFtaWx5PSJBcmlhbCIsIGNvbG91cj0iYmxhY2siKSwgCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIAogICAgICAgIGxlZ2VuZC5kaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsIAogICAgICAgIGxlZ2VuZC5ib3ggPSAidmVydGljYWwiLCAKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygxLDMsMSwzKSwgImxpbmVzIiksIAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImJsYWNrIiwgZmlsbD1OQSwgc2l6ZT0wLjUpKSArCiAgI2NoYW5nZSB0aGUgY29sb3VycwogICNzY2FsZV9jb2xvdXJfdmlyaWRpcyhvcHRpb24gPSAiaW5mZXJubyIsIGd1aWRlID0gImNvbG91cmJhciIsIG5hLnZhbHVlPSJ3aGl0ZSIsIGJlZ2luID0gMCwgZW5kID0gMSwgZGlyZWN0aW9uID0gMSkgKwogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBjaGFuZ2UgeCBheGlzIGxhYmVsCiAgIyBsYWJzKHggPSAiTWFya2VyIEdlbmVzIiwgeSA9ICJDbHVzdGVyIiwgdGl0bGUgPSAiRXhwcmVzc2lvbiBvZiBNYXJrZXIgR2VuZXMgYnkgQ2x1c3RlciIpIAogIGxhYnMoeCA9ICIiLCB5ID0gIiIsIHRpdGxlID0gIiIpICsKICAjIyBhZGQgYXJyb3dzCiAgI2Fubm90YXRlKCJzZWdtZW50IiwgeCA9IDUuNSwgeGVuZCA9IDUuNSwgeSA9IDIxLjUsIHllbmQgPSAyNSwgY29sb3VyID0gImdyZWVuIiwgc2l6ZT0xLCBhbHBoYT0xLCBhcnJvdz1hcnJvdyhsZW5ndGg9dW5pdCgwLjMwLCJjbSIpLCB0eXBlID0gImNsb3NlZCIpKSArCiAgI2Fubm90YXRlKCJzZWdtZW50IiwgeCA9IDUuNSwgeGVuZCA9IDUuNSwgeSA9IDE2LjUsIHllbmQgPSAyMS41LCBjb2xvdXIgPSAicmVkIiwgc2l6ZT0xLCBhbHBoYT0xLCBhcnJvdz1hcnJvdyhsZW5ndGg9dW5pdCgwLjMwLCJjbSIpLCB0eXBlID0gImNsb3NlZCIpKSArCiAgI2Fubm90YXRlKCJzZWdtZW50IiwgeCA9IDUuNSwgeGVuZCA9IDUuNSwgeSA9IDAsIHllbmQgPSAxNS41LCBjb2xvdXIgPSAiZ3JleSIsIHNpemU9MSwgYWxwaGE9MSwgYXJyb3c9YXJyb3cobGVuZ3RoPXVuaXQoMC4zMCwiY20iKSwgdHlwZSA9ICJjbG9zZWQiKSkgKwogICMjIGFubm90YXRlIGFzZXgKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gKGxlbmd0aChjKGFzZXh1YWxfZWFybHlfY2x1c3RlcnMsIGFzZXh1YWxfbGF0ZV9jbHVzdGVycykpKzAuNSkpLCBzaXplID0gMC41LCBsaW5ldHlwZT0gJ2Rhc2hlZCcpICsKICAjIyBhbm5vdGF0ZSBiaXBvdGVudGlhbAogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAobGVuZ3RoKGMoYXNleHVhbF9lYXJseV9jbHVzdGVycywgYXNleHVhbF9sYXRlX2NsdXN0ZXJzLCBiaXBvdGVudGlhbF9jbHVzdGVycykpKzAuNSkpLCBzaXplID0gMC41LCBsaW5ldHlwZT0gJ2Rhc2hlZCcpICsKICAjIyBhbm5vdGF0ZSBzZXhlcwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAobGVuZ3RoKGMoYXNleHVhbF9lYXJseV9jbHVzdGVycywgYXNleHVhbF9sYXRlX2NsdXN0ZXJzLCBiaXBvdGVudGlhbF9jbHVzdGVycywgbWFsZV9jbHVzdGVycykpKzAuNSkpLCBzaXplID0gMC41LCBsaW5ldHlwZT0gJ2Rhc2hlZCcpICsKICAjIyBjaGFuZ2UgbGFiZWwgb24gYm90dG9tIG9mIHBsb3Qgc28gd2UgY2FuIGluZGljYXRlIG1hcmtlcnMKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IHJldihjKCJnZDEiLCAibWQxIiwgIm1kMiIsICJtZDMiLCAibWQ0IiwgIm1kNSIsICJmZDEiLCAiZmQyIiwgImZkMyIsICJmZDQiLCAibXNwOCIsICJtc3AxIiwgIm1nMSIsICJjY3AyIiwgImFwMmciKSkpICsKICAjIyBjaGFuZ2UgbGFiZWwgb24gYm90dG9tIG9mIHBsb3Qgc28gd2UgY2FuIGluZGljYXRlIG1hcmtlcnMKICBzY2FsZV95X2Rpc2NyZXRlKGxhYmVscyA9IGMoIkFzZXh1YWwgMSIsICJBc2V4dWFsIDIiICwgIkFzZXh1YWwgMyIsICJBc2V4dWFsIDQiLCAiQXNleHVhbCA1IiwgIkFzZXh1YWwgNiIsICJBc2V4dWFsIDciLCAiQXNleHVhbCA4IiwgICJBc2V4dWFsIDkiLCAiQXNleHVhbCAxMCIsICJBc2V4dWFsIDExIiwgIkFzZXh1YWwgMTIiLCAiQXNleHVhbCAxMyIsICJBc2V4dWFsIDE0IiwgIkFzZXh1YWwgMTUiLCAiQXNleHVhbCAxNiIsICJBc2V4dWFsIDE3IiwgIlByb2dlbml0b3IiLCAiTWFsZSAxIiwgIk1hbGUgMiIsICJGZW1hbGUgMSIsICJGZW1hbGUgMiIsICJGZW1hbGUgMyIpKSArCiAgIyMgY2hhbmdlIG5hbWUgb2YgbGVnZW5kcwogIGd1aWRlcyhjb2w9Z3VpZGVfY29sb3JiYXIodGl0bGUgPSAnU2NhbGVkIEF2ZXJhZ2UgRXhwcmVzc2lvbicpLAogICAgICAgICBzaXplPWd1aWRlX2xlZ2VuZCgiJSBvZiBjZWxscyBleHByZXNzaW5nIikpCgojIyB2aWV3CiNwcmludChkb3RfcGxvdF9tYXJrZXJzKQoKcGxvdCA8LSBwbG90X2dyaWQoaDQsIGgzLCBoMSwgZG90X3Bsb3RfbWFya2VycywgYWxpZ24gPSAidiIsIG5jb2wgPSAxLCBheGlzID0gInRiIiwgcmVsX2hlaWdodHMgPSBjKDAuNSwgMC41LCAwLjUsIDE4KSkgCgpkb3RfcGxvdCA8LSBwbG90X2dyaWQocGxvdCwgbGVnZW5kX2gzLCBsZWdlbmRfaDQsIG5yb3cgPSAxLCByZWxfd2lkdGhzID0gYygxMCwgMS41LCAxLjUpKQoKZG90X3Bsb3QKYGBgCgpzYXZlCmBgYHtyfQpnZ3NhdmUoIi4uL2ltYWdlc190b19leHBvcnQvZG90X3Bsb3RfYWxsLnBuZyIsIHBsb3QgPSBkb3RfcGxvdCwgZGV2aWNlID0gInBuZyIsIHBhdGggPSBOVUxMLCBzY2FsZSA9IDEsIHdpZHRoID0gMjkuNywgaGVpZ2h0ID0gMjEsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKCiMgOS4gU3Vic2V0IHNleHVhbCBjZWxscyB7LnRhYnNldH0KCk1ha2UgYSBzdWJzZXR0ZWQgU2V1cmF0IG9iamVjdCBvZiBzZXh1YWwgY2VsbHMuIAoKSW5jbHVkZSB0aGUgcHJlLWJyYW5jaCB0b28gYXMgd2VsbCBhcyBhbnkgd2VpcmQgY2x1c3RlcnMgdGhhdCBtYXkgaGF2ZSBjbHVzdGVyZWQgb3V0LiAKCml0J3MgYmVlbiBhIHdoaWxlIHNpbmNlIHdlIGxvb2tlZCBhdCB0aGUgY2x1c3RlcnMgc28gbGV0J3MgY2hlY2sgdGhlbSBvdXQgYWdhaW46CmBgYHtyLCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQojIyBQbG90CkRpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgbGFiZWwgPSBUUlVFLCByZXBlbCA9IEZBTFNFLCBwdC5zaXplID0gMC4wNSwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiKSArIGNvb3JkX2ZpeGVkKCkKCiMjIHBsb3QKbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzJdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbM11dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s0XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzVdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbNl1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s3XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzhdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbOV1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxMF1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxMV1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxMl1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxM11dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxNF1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxNV1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxNl1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxN11dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxOF1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxOV1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1syMF1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1syMV1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1syMl1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1syM11dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1syNF1dCmBgYAoKIyMjIERlZmluZSBjZWxscyBhbmQgc3Vic2V0CmBgYHtyfQphc2V4dWFsX2Vhcmx5X2NsdXN0ZXJzIDwtIGMoOSwgNCwgMTUsIDgsIDEsIDE0LCAyLCAxMCwgMywgMCwgNiwgNSkKYXNleHVhbF9sYXRlX2NsdXN0ZXJzIDwtIGMoNywgMTIsIDE4LCAyMCwgMjMpCmJpcG90ZW50aW9uYWxfZWFybHlfY2x1c3RlcnMgPC0gIyAwPwpiaXBvdGVudGlhbF9jbHVzdGVycyA8LSBjKDExKSAKbWFsZV9jbHVzdGVycyA8LSBjKDE2LCAxMykKZmVtYWxlX2NsdXN0ZXJzIDwtIGMoMjEsIDIyLCAxNywgMTkpCgojIyBkZWZpbmUgY2VsbHMKY2VsbF9uYW1lc19zdWJzZXRfbW9ub2NsZV9pZHMgPC0gcm93bmFtZXModGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGFbdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkbW9ub2NsZV9zZXggJWluJSBjKCJBc2V4dWFsX0Vhcmx5IiwgIkJpcG90ZW50aWFsIiwgIk1hbGUiLCAiRmVtYWxlIiksIF0pCgojIyAzLCAwLCA2LCA1IGFyZSBlYXJseSBjbHVzdGVycyBvZiBhc2V4dWFscyBiZWZvcmUgdGhlIGJyYW5jaApjZWxsX25hbWVzX3N1YnNldF9jbHVzdGVyX2lkcyA8LSByb3duYW1lcyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YVt0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnMgJWluJSBjKG1hbGVfY2x1c3RlcnMsIGZlbWFsZV9jbHVzdGVycywgYmlwb3RlbnRpYWxfY2x1c3RlcnMsIDMsIDAsIDYsIDUpLCBdKQoKY2VsbF9uYW1lc19zdWJzZXRfaW50ZXJzZWN0IDwtIGludGVyc2VjdChjZWxsX25hbWVzX3N1YnNldF9tb25vY2xlX2lkcywgY2VsbF9uYW1lc19zdWJzZXRfY2x1c3Rlcl9pZHMpCgojIyBzdWJzZXQgY2VsbHMgaW50byBuZXcgb2JqZWN0CnRlbnguanVzdHd0LmludGVncmF0ZWQuc2V4IDwtIHN1YnNldCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBjZWxscyA9IGNlbGxfbmFtZXNfc3Vic2V0X2ludGVyc2VjdCkKYGBgCgojIyMgaW5zcGVjdC9jaGVjawpgYGB7cn0KIyMgaW5zcGVjdCBvYmplY3QKdGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXgKCiMjIGxvb2sgYXQgb3JpZ2luYWwgVU1BUApEaW1QbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQuc2V4LCBsYWJlbCA9IFRSVUUsIHJlcGVsID0gVFJVRSwgcHQuc2l6ZSA9IDAuMSwgc3BsaXQuYnkgPSAiZXhwZXJpbWVudCIsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIikgKyBjb29yZF9maXhlZCgpCmBgYAoKIyMjIFJlbW92ZSBjb250YW1pbmFudCBhc2V4dWFsIGNlbGxzCgp3ZSB3YW50IHRvIHJlbW92ZToKYGBge3J9CiMjIGxvb2sgYXQgb3JpZ2luYWwgVU1BUApwbG90X3NleHVhbF9zdWJzZXR0aW5nIDwtIERpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXgsIGxhYmVsID0gVFJVRSwgcmVwZWwgPSBUUlVFLCBwdC5zaXplID0gMC4xLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIpICsgCiAgY29vcmRfZml4ZWQoKSArIAogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAtMSwgYWxwaGEgPSA1KSkKCnBsb3Rfc2V4dWFsX3N1YnNldHRpbmcKYGBgCgpgYGB7cn0KIyMgZXh0cmFjdCBjZWxsIGVtYmVkZGluZ3MKZGZfc2V4X2NlbGxfZW1iZWRkaW5ncyA8LSBhcy5kYXRhLmZyYW1lKHRlbnguanVzdHd0LmludGVncmF0ZWQuc2V4QHJlZHVjdGlvbnNbWyJ1bWFwIl1dQGNlbGwuZW1iZWRkaW5ncykKCiMjIHN1YnNldCBhbnl0aGluZyBsb3dlciB0aGFuIC0wLjggaW4gVU1BUCAyIGFuZCAtMC4xIGluIFVNQVAgMQpyZW1vdmVfY2VsbHMgPC0gcm93Lm5hbWVzKGRmX3NleF9jZWxsX2VtYmVkZGluZ3Nbd2hpY2goZGZfc2V4X2NlbGxfZW1iZWRkaW5ncyRVTUFQXzEgPCAtMSksIF0pCgojIyBwbG90IHRoZXNlIGNlbGxzCkRpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXgsIGxhYmVsID0gRkFMU0UsIHJlcGVsID0gVFJVRSwgcHQuc2l6ZSA9IDAuMSwgY2VsbHMuaGlnaGxpZ2h0ID0gcmVtb3ZlX2NlbGxzLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIpICsgCiAgY29vcmRfZml4ZWQoKSArIAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiIzAwMDAwMCIsICIjZjU0ZTFlIikpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJjZWxscyBoaWdobGlnaHRlZCB3aWxsIGJlIHJlbW92ZWQiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKCiMjIEZpbmFsIFN1YnNldApgYGB7cn0KIyMgbWFrZSBrZWVwIGNlbGxzIGZyb20gdGhlIHJlbW92ZV9jZWxscwojIyBtYWtlIHRoZSBub3QgaW4gZnVuY3Rpb24KJyVuaSUnIDwtIE5lZ2F0ZSgnJWluJScpCmtlZXBfY2VsbHMgPC0gY29sbmFtZXModGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXgpW3doaWNoKGNvbG5hbWVzKHRlbnguanVzdHd0LmludGVncmF0ZWQuc2V4KSAlbmklIHJlbW92ZV9jZWxscyldCgojIyBzdWJzZXQKdGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXggPC0gc3Vic2V0KHRlbnguanVzdHd0LmludGVncmF0ZWQuc2V4LCBjZWxscyA9IGtlZXBfY2VsbHMpCgojIyBpbnNwZWN0CnRlbnguanVzdHd0LmludGVncmF0ZWQuc2V4CmBgYAoKY29weSBvbGQgY2x1c3RlcnMgb3ZlcgpgYGB7cn0KIyMgY29weSBvbGQgY2x1c3RlcnMKdGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXggPC0gQWRkTWV0YURhdGEodGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXgsIHRlbnguanVzdHd0LmludGVncmF0ZWQuc2V4QG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnMsIGNvbC5uYW1lID0gInBvc3RfaW50ZWdyYXRpb25fY2x1c3RlcnMiKQpgYGAKCiMgMTAuIFNleCBhc3NpZ25tZW50IG9mIG11dGFudHMgCgojIyBBLiBTZXVyYXQgTWV0aG9kCgpgYGB7cn0KIyMgZmluZCB0cmFuc2ZlciBhbmNob3JzCkRlZmF1bHRBc3NheSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkKSA8LSAiaW50ZWdyYXRlZCIKbWVyZ2UuYW5jaG9ycyA8LSBGaW5kVHJhbnNmZXJBbmNob3JzKHJlZmVyZW5jZSA9IHRlbnguanVzdHd0LmludGVncmF0ZWQsIHF1ZXJ5ID0gR0NTS09fbXV0YW50cywgCiAgICBkaW1zID0gMTozMCkKCiMjIHRyYW5zZmVyIGRhdGEgYmV0d2VlbiByZWYgYW5kIHF1ZXJ5CnByZWRpY3Rpb25zIDwtIFRyYW5zZmVyRGF0YShhbmNob3JzZXQgPSBtZXJnZS5hbmNob3JzLCByZWZkYXRhID0gdGVueC5qdXN0d3QuaW50ZWdyYXRlZCRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nLCAKICAgIGRpbXMgPSAxOjMwKQoKIyMgYWRkIG1ldGEgZGF0YSB0byBvYmplY3QKR0NTS09fbXV0YW50cyA8LSBBZGRNZXRhRGF0YShHQ1NLT19tdXRhbnRzLCBtZXRhZGF0YSA9IHByZWRpY3Rpb25zKQoKIyMgbmV3IG9iamVjdCBmcm9tIHRoaXMKbXV0YW50X3NldXJhdCA8LSBHQ1NLT19tdXRhbnRzCgojIyBsb29rIGF0IGJyZWFrZG93biBvZiBtdXRhbnQgYnkgZGVzaWduYXRpb24KZGYgPC0gYXMuZGF0YS5mcmFtZShtdXRhbnRfc2V1cmF0QG1ldGEuZGF0YSkKdGFibGUoZGYkcHJlZGljdGVkLmlkLCBkZiRpZGVudGl0eV9uYW1lX3VwZGF0ZWQpCmBgYAoKYGBge3J9CiMjIHNlZSBob3cgdGhpcyBvdmVybGFwcyB3aXRoIGZsdW9yZXNjZW5jZSBzb3J0ZWQgb24gZm9yIDgyMCB0byBjb25maXJtIGFjY3VyYWN5CmRmXzgyMCA8LSBkZltkZiRnZW5ldGljX2JhY2tncm91bmQgPT0iUEJBTktBXzgyMCIsIF0KdGFibGUoZGZfODIwJHByZWRpY3RlZC5pZCwgZGZfODIwJGZsdW9yZXNlbmNlX3NvcnRlZF9vbikKYGBgCgppbnNwZWN0IGdkMQpgYGB7cn0KZGZbd2hpY2goZGYkcHJlZGljdGVkLmlkID09ICJGZW1hbGVfMSIgJiBkZiRpZGVudGl0eV9uYW1lX3VwZGF0ZWQgPT0gImdkMSIpLCBdWywgMTE4OjE0Nl0KYGBgCgoKQ2FsY3VsYXRlIHNleCByYXRpb3MKYGBge3J9CiMjIHVzZSBkZXNpZ25hdGlvbnMgYWJvdmUgZm9yIHNleGVzCm1hbGVfY2VsbHMgPC0gcm93bmFtZXMobXV0YW50X3NldXJhdEBtZXRhLmRhdGFbbXV0YW50X3NldXJhdEBtZXRhLmRhdGEkcHJlZGljdGVkLmlkID09ICJNYWxlIiwgXSkKZmVtYWxlX2NlbGxzIDwtIHJvd25hbWVzKG11dGFudF9zZXVyYXRAbWV0YS5kYXRhW211dGFudF9zZXVyYXRAbWV0YS5kYXRhJHByZWRpY3RlZC5pZCA9PSAiRmVtYWxlIiwgXSkKc3MyX211dGFudHNfZmluYWxfbWFsZSA8LSBzdWJzZXQobXV0YW50X3NldXJhdCwgY2VsbHMgPSBtYWxlX2NlbGxzKQpzczJfbXV0YW50c19maW5hbF9mZW1hbGUgPC0gc3Vic2V0KG11dGFudF9zZXVyYXQsIGNlbGxzID0gZmVtYWxlX2NlbGxzKQoKIyMgaW5zcGVjdApzczJfbXV0YW50c19maW5hbF9tYWxlCnNzMl9tdXRhbnRzX2ZpbmFsX2ZlbWFsZQpgYGAKCmBgYHtyfQojIyBjYWxjdWxhdGUgc2V4IHJhdGlvcwojI3N1YnNldCBvdXQgSCwgc29ydGVkIGNlbGxzOgpkZl9tYWxlIDwtIHNzMl9tdXRhbnRzX2ZpbmFsX21hbGVAbWV0YS5kYXRhW3NzMl9tdXRhbnRzX2ZpbmFsX21hbGVAbWV0YS5kYXRhJGV4Y2x1ZGVfZm9yX3NleF9yYXRpbyA9PSBGQUxTRSxdCgpkaW0oZGZfbWFsZSkKCmRmX2ZlbWFsZSA8LSBzczJfbXV0YW50c19maW5hbF9mZW1hbGVAbWV0YS5kYXRhW3NzMl9tdXRhbnRzX2ZpbmFsX2ZlbWFsZUBtZXRhLmRhdGEkZXhjbHVkZV9mb3Jfc2V4X3JhdGlvID09IEZBTFNFLF0KCmRpbShkZl9mZW1hbGUpCgojIyBtYWtlIGRhdGFmcmFtZQpkZl9zZXhfcmF0aW8gPC0gbWVyZ2UoCiAgYXMuZGF0YS5mcmFtZSh0YWJsZShkZl9tYWxlJHN1Yl9uYW1lX3VwZGF0ZWQpKSwgCiAgYXMuZGF0YS5mcmFtZSh0YWJsZShkZl9mZW1hbGUkc3ViX25hbWVfdXBkYXRlZCkpLCAKICBieSA9ICJWYXIxIiwgYWxsPVRSVUUpCgojIG9yIHVzZSBpZGVudGl0eV91cGRhdGVkCgojIyBhZGQgbmFtZXMKbmFtZXMoZGZfc2V4X3JhdGlvKSA8LSBjKCJnZW5vdHlwZSIsICJtYWxlIiwgImZlbWFsZSIpCgojIyBjaGFuZ2UgdGhlIE5BcyB0byAwCmRmX3NleF9yYXRpb1tpcy5uYShkZl9zZXhfcmF0aW8pXSA8LSAwCgojIyBjb2xsYXBzZSA4MjAgd2lsZC10eXBlcyB0b2dldGhlcgpjb21iaW5lZF9tIDwtIGRmX3NleF9yYXRpb1tkZl9zZXhfcmF0aW8kZ2Vub3R5cGUgPT0gIldULTgyMF8zXzUiLCBdJG1hbGUgKyBkZl9zZXhfcmF0aW9bZGZfc2V4X3JhdGlvJGdlbm90eXBlID09ICJXVC04MjAiLCBdJG1hbGUKY29tYmluZWRfZiA8LSBkZl9zZXhfcmF0aW9bZGZfc2V4X3JhdGlvJGdlbm90eXBlID09ICJXVC04MjBfM181IiwgXSRmZW1hbGUgKyBkZl9zZXhfcmF0aW9bZGZfc2V4X3JhdGlvJGdlbm90eXBlID09ICJXVC04MjAiLCBdJGZlbWFsZQpkZl9zZXhfcmF0aW8gPC0gcmJpbmQoZGZfc2V4X3JhdGlvLCBjKCJXVC04MjAtY29tYmluZWQiLCBjb21iaW5lZF9tLCBjb21iaW5lZF9mKSkKIyByZW1vdmUgb2xkIHJvd3MKZGZfc2V4X3JhdGlvIDwtIGRmX3NleF9yYXRpb1std2hpY2goZGZfc2V4X3JhdGlvJGdlbm90eXBlID09ICJXVC04MjBfM181IiB8IGRmX3NleF9yYXRpbyRnZW5vdHlwZSA9PSAiV1QtODIwIiksIF0KIyBuZWVkIHRvIG1ha2UgbnVtZXJpYyBhZ2FpbgpkZl9zZXhfcmF0aW8kbWFsZSA8LSBhcy5udW1lcmljKGRmX3NleF9yYXRpbyRtYWxlKQpkZl9zZXhfcmF0aW8kZmVtYWxlIDwtIGFzLm51bWVyaWMoZGZfc2V4X3JhdGlvJGZlbWFsZSkKZGZfc2V4X3JhdGlvJGdlbm90eXBlIDwtIGFzLmNoYXJhY3RlcihkZl9zZXhfcmF0aW8kZ2Vub3R5cGUpCiMgYWRkIG5hbWUgZm9yIFdUIGNvbWJpbmVkCmRmX3NleF9yYXRpbyRnZW5vdHlwZVsxN10gPC0gIldULTgyMC1jb21iaW5lZCIKCiMjIGNhbGN1bGF0ZSBzZXggcmF0aW8KZGZfc2V4X3JhdGlvJHNleF9yYXRpbyA8LSAoZGZfc2V4X3JhdGlvJG1hbGUgKyAwLjEpLyhkZl9zZXhfcmF0aW8kZmVtYWxlICsgMC4xKQoKIyMgbG9nIHNleCByYXRpbwpkZl9zZXhfcmF0aW8kc2V4X3JhdGlvX2xvZyA8LSBsb2cxMChkZl9zZXhfcmF0aW8kc2V4X3JhdGlvKQoKIyN2aWV3CmRmX3NleF9yYXRpbwpgYGAKCmBgYHtyfQojIyByZW1vdmUgV1QtMiBiZWNhdXNlIGl0IGlzIHJlYWxseSBpbmFwcHJvcHJpYXRlIHRvIGhhdmUgYSBzZXggcmF0aW8gZm9yIHRoaXM6CmRmX3NleF9yYXRpbyA8LSBkZl9zZXhfcmF0aW9bLXdoaWNoKGRmX3NleF9yYXRpbyRnZW5vdHlwZSA9PSAiV1QtbWQ1IiksXQpgYGAKCnBsb3QKYGBge3IsIGZpZy5oZWlnaHQgPSA3LCBmaWcud2lkdGggPSA2fQpsaWJyYXJ5KGxhdGV4MmV4cCkgIyBzbyB5b3UgY2FuIHBsb3QgdGhlIGZyYWN0aW9uLCBpdCdzIG9uIENSQU4gYGluc3RhbGwucGFja2FnZXMoImxhdGV4MmV4cCIpYAoKIyMgbWFrZSBleHRyYSBjb2x1bW4gZm9yIHBsb3R0aW5nIGFlc3RoZXRpY3M6CmRmX3NleF9yYXRpbyRhYm92ZSA8LSBkZl9zZXhfcmF0aW8kc2V4X3JhdGlvX2xvZyA+IDAKCiMjIG1ha2UgZXh0cmEgY29sdW1uIHdpdGggcmF0aW8gaW4gaXQ6CmRmX3NleF9yYXRpbyRnZW5vdHlwZV93aXRoX24gPC0gcGFzdGUwKGRmX3NleF9yYXRpbyRnZW5vdHlwZSwgIiAoIiwgZGZfc2V4X3JhdGlvJG1hbGUsICIvIiwgZGZfc2V4X3JhdGlvJGZlbWFsZSwgIikiKQoKIyMgcmVvcmRlciBnZW5vdHlwZSBzbyBpdCBpcyBpbiB0aGUgY29ycmVjdCBvcmRlciBmb3IgcGxvdHRpbmcKZGZfc2V4X3JhdGlvJGdlbm90eXBlX3dpdGhfbiA8LSBmYWN0b3IoZGZfc2V4X3JhdGlvJGdlbm90eXBlX3dpdGhfbiwgbGV2ZWxzID0gZGZfc2V4X3JhdGlvJGdlbm90eXBlX3dpdGhfbltvcmRlcihkZl9zZXhfcmF0aW8kc2V4X3JhdGlvX2xvZyldKQoKIyMgcGxvdApzZXhfcmF0aW9fcGxvdCA8LSBnZ3Bsb3QoZGZfc2V4X3JhdGlvLCBhZXMoc2V4X3JhdGlvX2xvZywgZ2Vub3R5cGVfd2l0aF9uLCBjb2xvciA9IGFib3ZlKSkgKwogICAgICAjIyBhZGQgdGhlIGxpbmVzIGZvciB0aGUgbG9sbGlwb3AgcGxvdAogICAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAwLCB5ID0gZ2Vub3R5cGVfd2l0aF9uLCB4ZW5kID0gc2V4X3JhdGlvX2xvZywgeWVuZCA9IGdlbm90eXBlX3dpdGhfbiksIGNvbG9yID0gImdyZXk1MCIpICsKICAgICAgIyMgYWRkIHRoZSBwb2ludHMgZm9yIHRoZSBsb2xsaXBvcCBwbG90CiAgICAgIGdlb21fcG9pbnQoYWVzKHNpemUgPSA0KSkgKwogICAgICAjIyBhZGQgdGhlIHdpbGQtdHlwZSByZWN0YW5nbGUKICAgICAgYW5ub3RhdGUoInJlY3QiLCB4bWluPSAtMC4yMzE4MjQ3OCwgeG1heCA9IDEuMDAxMDU3OTcsIHltaW49LUluZiAsIHltYXg9SW5mLCBhbHBoYT0wLjQsIGNvbG9yPU5BLGxpbmV0eXBlID0gMiwgZmlsbD0iIzk5OTk5OSIpICsKICAgICAgIyMgbWFrZSBwcmV0dGllcgogICAgICB0aGVtZV9jbGFzc2ljKCkgKwogICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTYsIGZhbWlseT0iQXJpYWwiKSkgKyAKICAgICAgIyMgY2hhbmdlIGF4aXMgbGFiZWxzCiAgICAgIGxhYnMoeSA9IFRlWCgiJEdlbm90eXBlXCBcXGxlZnQoXFxmcmFje25fe21hbGV9fXtuX3tmZW1hbGV9fVxccmlnaHQpJCIpKSArCiAgICAgICNsYWJzKHkgPSBleHByZXNzaW9uKHBhc3RlKCJHZW5vdHlwZSIsIGdyb3VwKCIoIiwgZnJhYyhwYXN0ZSgibiBtYWxlIiksICJuIGZlbWFsZSIpLCAiKSIpKSkpICsKICAgICAgeGxhYihleHByZXNzaW9uKHBhc3RlKCJTZXggUmF0aW8gKCIsIGxvZ1sxMF0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAoIigiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyYWMocGFzdGUoIm4gbWFsZSArIDAuMSIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlKCJuIGZlbWFsZSArIDAuMSIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiKSIpLCAiKSIgKSkpICsKICAgICAgIyMgY2hhbmdlIGNvbG91cnMgb2YgbG9sbGlwb3BzCiAgICAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygiI2E1MmIxZSIsICIjMDE2YzAwIikpICsKICAgICAgIyMgYW5ub3RhdGUgcGhlbm90eXBlcwogICAgICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gNS41KSkgIysKICAgICAgI2dlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAxNC41KSkKCnByaW50KHNleF9yYXRpb19wbG90KQoKIyMjIENIQU5HRSBUTyBCSUcgQlJBQ0tFVCBIRVJFOiBodHRwczovL3d3dy5vdmVybGVhZi5jb20vbGVhcm4vbGF0ZXgvQnJhY2tldHNfYW5kX1BhcmVudGhlc2VzIAoKI3Bhc3RlKCJTZXggUmF0aW8iLCAiXG4iLCAibG9nMTAoKG4gbWFsZSArIDAuMSkvKG4gZmVtYWxlICsgMC4xKSkiKQojdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTE2LCBmYW1pbHk9IkFyaWFsIikpCgojIyBmcmFjdGlvbiB0aXRsZXM6IGh0dHBzOi8vZ3JvdXBzLmdvb2dsZS5jb20vZm9ydW0vIyF0b3BpYy9nZ3Bsb3QyL2JnTlJuWjgyaEpZIAojIyBodHRwczovL3VjLXIuZ2l0aHViLmlvL2xvbGxpcG9wCgojZ2dzYXZlKGZpbGVuYW1lID0gIi4uL2ltYWdlc190b19leHBvcnQvc2V4X3JhdGlvX3Bsb3QucG5nIiwgZGV2aWNlID0gInBuZyIsIHdpZHRoID0gNywgaGVpZ2h0ID0gNywgdW5pdHMgPSAiaW4iKQpgYGAKCiMjIEIuIFNDTUFQIE1ldGhvZAoKIyMjIEJ1aWxkIHRoZSBpbmRleAoKYGBge3J9CiMjIyBNYWtpbmcgYW4gb3J0aG9sb2cgcmVmZXJlbmNlIGluZGV4CgojIyBsb2FkIGluIG1jYSBkYXRhCiNjb3VudHMgPC0gcmVhZC5jc3YoIi4uL3NjbWFwL2FsbHBiMTB4X2NvdW50cy5jc3YiLCByb3cubmFtZXMgPSAxKQojcGhlbm8gPC0gcmVhZC5jc3YoIi4uL3NjbWFwL2FsbHBiMTB4X3BoZW5vLmNzdiIpCiNnZ3Bsb3QocGhlbm8sIGFlcyh4PVBDMl8zZCwgeSA9IFBDM18zZCxjb2xvdXI9YWJzY2x1c3QzKSkgKyBnZW9tX3BvaW50KCkKCiMjIGxvYWQgcmVxdWlyZWQgbGlicmFyaWVzCmxpYnJhcnkoc2NtYXApICNodHRwczovL2Jpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvcmVsZWFzZS9iaW9jL2h0bWwvc2NtYXAuaHRtbCAKbGlicmFyeShTaW5nbGVDZWxsRXhwZXJpbWVudCkgIwoKI3ByZXAgdGhlIFNDRSwgaWYgd2FzIG9yaWdpbmFsbHkgYSBTdWVyYXQgb2JqZWN0IG5lZWQgdGhlIGRmcyB0byBiZSByZWd1bGFyIG1hdHJpY2VzCiNwYl9maWx0ZXJlZF9zY2Vfb3J0aCA8LSBwYl9maWx0ZXJlZF9zY2Vfb3J0aFssIGNvbERhdGEocGJfZmlsdGVyZWRfc2NlX29ydGgpJGFic2NsdXN0MyAhPSAiOCJdCiNzY2UgPC0gcGJfZmlsdGVyZWRfc2NlX29ydGgKI3BjYSA8LSBwbG90UENBKHNjZSkKI3BjcyA8LSBwY2EkZGF0YQojdGFibGUocm93bmFtZXMocGNzKT09Y29sbmFtZXMoc2NlKSkKI2NvbERhdGEoc2NlKSA8LSBjYmluZChjb2xEYXRhKHNjZSksIHBjcykKI3Jvd0RhdGEoc2NlKSRmZWF0dXJlX3N5bWJvbCA8LSByb3dEYXRhKHNjZSkkZ2VuZQoKIyMgZXh0cmFjdCBkYXRhIGZyb20gU2V1cmF0CiNjZWxsc190ZW54IDwtIHJvd25hbWVzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhW3doaWNoKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJGV4cGVyaW1lbnQgPT0gInRlbnhfNWsiKSwgXSkKI3RlbnguanVzdHd0LmludGVncmF0ZWQuMTBrIDwtIHN1YnNldCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBjZWxscyA9IGNlbGxzX3RlbngpCmNvdW50cyA9IGFzLm1hdHJpeChHZXRBc3NheURhdGEodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgc2xvdCA9ICJjb3VudHMiLCBhc3NheSA9ICJSTkEiKSkKcGhlbm8gPSBhcy5kYXRhLmZyYW1lKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhKQoKIyMgYWRkIFVNQVAgY29vcmRpbmF0ZXMKZGZfc2V4X2NlbGxfZW1iZWRkaW5ncyA8LSBhcy5kYXRhLmZyYW1lKHRlbnguanVzdHd0LmludGVncmF0ZWRAcmVkdWN0aW9uc1tbInVtYXAiXV1AY2VsbC5lbWJlZGRpbmdzKQpwaGVubyA8LSBjYmluZChwaGVubywgZGZfc2V4X2NlbGxfZW1iZWRkaW5ncykKCiMjIFNldCB1cCBvYmplY3QKc2NlIDwtIFNpbmdsZUNlbGxFeHBlcmltZW50KGxpc3QoY291bnRzPWNvdW50cyksCiAgICBjb2xEYXRhPURhdGFGcmFtZShsYWJlbD1waGVubyksCiAgICByb3dEYXRhPURhdGFGcmFtZShmZWF0dXJlX3N5bWJvbD1yb3duYW1lcyhjb3VudHMpKSkKc2NlCgojIyBtYW51YWwgbG9nZ2luZwojY291bnRzXzEgPC0gYXNzYXkoc2NlLCAiY291bnRzIikKI2xpYnNpemVzIDwtIGNvbFN1bXMoY291bnRzXzEpCiNzaXplLmZhY3RvcnMgPC0gbGlic2l6ZXMvbWVhbihsaWJzaXplcykKI2xvZ2NvdW50cyhzY2UpIDwtIGxvZzIodCh0KGNvdW50c18xKS9zaXplLmZhY3RvcnMpICsgMSkKI2NvdW50cyhzY2UpIDwtIGFzLm1hdHJpeChjb3VudHMoc2NlKSkKI2xvZ2NvdW50cyhzY2UpIDwtIGFzLm1hdHJpeChsb2djb3VudHMoc2NlKSkKbG9nY291bnRzKHNjZSkgPC0gYXMubWF0cml4KEdldEFzc2F5RGF0YSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBzbG90ID0gImRhdGEiLCBhc3NheSA9ICJSTkEiKSkKCiMjIHJlbW92ZSBmZWF0dXJlcyB3aXRoIGR1cGxpY2F0ZWQgbmFtZXMKc2NlIDwtIHNjZVshZHVwbGljYXRlZChyb3duYW1lcyhzY2UpKSwgXQoKIyMgYnVpbGQgc2NtYXAtY2VsbCByZWZlcmVuY2UgaW5kZXgsIHNhdmUgdGhpcyByZHMKc2NlIDwtIHNlbGVjdEZlYXR1cmVzKHNjZSwgc3VwcHJlc3NfcGxvdCA9IEZBTFNFLCBuX2ZlYXR1cmVzID0gMjAwMCkKdGFibGUocm93RGF0YShzY2UpJHNjbWFwX2ZlYXR1cmVzKQpzZXQuc2VlZCgxKQpzY2UgPC0gaW5kZXhDZWxsKHNjZSwgTSA9IDUwLCBrID0gODApCm5hbWVzKG1ldGFkYXRhKHNjZSkkc2NtYXBfY2VsbF9pbmRleCkKI2xlbmd0aChtZXRhZGF0YShzY2UpJHNjbWFwX2NlbGxfaW5kZXgkc3ViY2VudHJvaWRzKQojZGltKG1ldGFkYXRhKHNjZSkkc2NtYXBfY2VsbF9pbmRleCRzdWJjZW50cm9pZHNbWzFdXSkKI21ldGFkYXRhKHNjZSkkc2NtYXBfY2VsbF9pbmRleCRzdWJjZW50cm9pZHNbWzFdXVssMTo1XQojZGltKG1ldGFkYXRhKHNjZSkkc2NtYXBfY2VsbF9pbmRleCRzdWJjbHVzdGVycykKCiNzYXZlUkRTKHBiX2ZpbHRlcmVkX3NjZV9vcnRoLCBmaWxlPSJwYl9maWx0ZXJlZF9zY2Vfb3J0aGluZGV4XzIwMTgxMTA5LnJkcyIpCmBgYAoKIyMjIE1hcCB0byB0aGUgaW5kZXgKCmBgYHtyfQojcm93RGF0YShwYl9maWx0ZXJlZF9zY2Vfb3J0aCkkZmVhdHVyZV9zeW1ib2wgPC0gcm93RGF0YShwYl9maWx0ZXJlZF9zY2Vfb3J0aCkkb3J0aF9uYW1lCiNyb3duYW1lcyhwYl9maWx0ZXJlZF9zY2Vfb3J0aCkgPC0gcm93RGF0YShwYl9maWx0ZXJlZF9zY2Vfb3J0aCkkb3J0aF9uYW1lCgojcHJlcCB0aGUgU0NFLCBpZiB3YXMgb3JpZ2luYWxseSBhIFN1ZXJhdCBvYmplY3QgbmVlZCB0aGUgZGZzIHRvIGJlIHJlZ3VsYXIgbWF0cmljZXMKI3BiX2ZpbHRlcmVkX3NjZV9vcnRoIDwtIHBiX2ZpbHRlcmVkX3NjZV9vcnRoWywgY29sRGF0YShwYl9maWx0ZXJlZF9zY2Vfb3J0aCkkYWJzY2x1c3QzICE9ICI4Il0KI3NjZSA8LSBwYl9maWx0ZXJlZF9zY2Vfb3J0aAojcGNhIDwtIHBsb3RQQ0Eoc2NlKQojcGNzIDwtIHBjYSRkYXRhCiN0YWJsZShyb3duYW1lcyhwY3MpPT1jb2xuYW1lcyhzY2UpKQoKI2NvbERhdGEoc2NlKSA8LSBjYmluZChjb2xEYXRhKHNjZSksIHBjcykKCm11dGFudHNfY291bnRzID0gYXMubWF0cml4KEdldEFzc2F5RGF0YShtdXRhbnRfc2V1cmF0LCBzbG90ID0gImNvdW50cyIsIGFzc2F5ID0gIlJOQSIpKQptdXRhbnRzX3BoZW5vID0gYXMuZGF0YS5mcmFtZShtdXRhbnRfc2V1cmF0QG1ldGEuZGF0YSkKCiNyb3dEYXRhKHNjZSkkZmVhdHVyZV9zeW1ib2wgPC0gcm93RGF0YShzY2UpJGdlbmUKbXV0YW50cy5zY2UgPC0gU2luZ2xlQ2VsbEV4cGVyaW1lbnQobGlzdChjb3VudHM9bXV0YW50c19jb3VudHMpLAogICAgY29sRGF0YT1EYXRhRnJhbWUobGFiZWw9bXV0YW50c19waGVubyksCiAgICByb3dEYXRhPURhdGFGcmFtZShmZWF0dXJlX3N5bWJvbD1yb3duYW1lcyhtdXRhbnRzX2NvdW50cykpKQptdXRhbnRzLnNjZQoKIyMgYWRkIGxvZyBjb3VudHMKIyMgbWFudWFsCiNjb3VudHNfMSA8LSBhc3NheShtdXRhbnRzLnNjZSwgImNvdW50cyIpCiNsaWJzaXplcyA8LSBjb2xTdW1zKGNvdW50c18xKQojc2l6ZS5mYWN0b3JzIDwtIGxpYnNpemVzL21lYW4obGlic2l6ZXMpCiNsb2djb3VudHMobXV0YW50cy5zY2UpIDwtIGxvZzIodCh0KGNvdW50c18xKS9zaXplLmZhY3RvcnMpICsgMSkKIyMgZnJvbSBzZXVyYXQKbG9nY291bnRzKG11dGFudHMuc2NlKSA8LSBhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKG11dGFudF9zZXVyYXQsIHNsb3QgPSAiZGF0YSIsIGFzc2F5ID0gIlJOQSIpKQoKI1Byb2plY3QgcXVlcnkgZGF0YSBzZXQgb250byBjZWxsIGluZGV4CnNjbWFwQ2VsbF9yZXN1bHRzIDwtIHNjbWFwQ2VsbCgKICBtdXRhbnRzLnNjZSwgCiAgbGlzdCh3dCA9IG1ldGFkYXRhKHNjZSkkc2NtYXBfY2VsbF9pbmRleAogICkKKQoKIyNMb29rIGludG8gdGhlIHJlc3VsdHMKIyBGb3IgZWFjaCBkYXRhc2V0IHRoZXJlIGFyZSB0d28gbWF0cmljaWVzLiBjZWxscyBtYXRyaXggY29udGFpbnMgdGhlIHRvcCAxMCAoc2NtYXAgZGVmYXVsdCkgY2VsbCBJRHMgb2YgdGhlIGNlbGxzIG9mIHRoZSByZWZlcmVuY2UgZGF0YXNldCB0aGF0IGEgZ2l2ZW4gY2VsbCBvZiB0aGUgcHJvamVjdGlvbiBkYXRhc2V0IGlzIGNsb3Nlc3QgdG86CiMgICAKIyAgIEdpdmUgYXNzaWdubWVudHMgaW4gdHdvIHdheXM6CiMgICAxLiBUYWtlIHRoZSB0b3AgY2VsbCBhc3NpZ25tZW50IGFicyBjbHVzdCwgaWYgY29zaW5lIHNpbWlsYXJpdHkgaXMgbGVzcyB0aGFuIDAuNCAob3IgYWRqdXN0IGlmIG5lZWRlZCkgbWFyayBhcyB1bmFzc2lnbmVkCiMgMi4gRm9yIHRoZSB0b3AgMyBuZWFyZXN0IG5laWdoYm9ycywgZ2V0IGEgbWVhbiBvZiB0aGUgUENBIGNvb3JkaW5hdGVzIGFuZCBzbmFwIHRvIHRoZSBuZWFyZXN0IGNlbGwgb2YgdGhvc2UgY29vcmRpbmF0ZXMuIElmIGFueSBvZiB0aGUgdG9wIHRocmVlIGNlbGxzIGFyZSBzaW0gYmVsb3cgMC40IHRoZW4gbWFyayBhcyB1bmFzc2lnbmVkLgoKCiMjVG9wIGNlbGwgYXNzaWdubWVudCBtZXRob2QKCiMjIGxvb2sgYXQgYXNzaWdubWVudHMKc2NtYXBDZWxsX3Jlc3VsdHMkd3QkY2VsbHNbLCAxOjNdCiMjIGdldCBjZWxsIGluZGV4ZXMgCmdldGNlbGxzIDwtIHNjbWFwQ2VsbF9yZXN1bHRzJHd0JGNlbGxzWzEsIF0KIyMgZXhjdHJhY3QgY2VsbHMgbWV0YWRhdGEgZnJvbSBpbmRleApjZHNjZSA8LSBjb2xEYXRhKHNjZSlbZ2V0Y2VsbHMsIF0KIyMgZXh0cmFjdCBzaW1pbGFyaXRpZXMKdG9wc2ltIDwtIHNjbWFwQ2VsbF9yZXN1bHRzJHd0JHNpbWlsYXJpdGllc1sxLCBdCiMjIGdldCBuYW1lIG9mIHRvcCBjZWxsIG1hdGNoZWQKbXV0YW50cy5zY2UkdG9wY2VsbCA8LSByb3duYW1lcyhjZHNjZSkKIyMgZ2V0IHNleCBpZAptdXRhbnRzLnNjZSR0b3BjZWxsX2FjIDwtIGNkc2NlJGxhYmVsLm1vbm9jbGVfc2V4CiMjIGdldCBjb29yZGluYXRlcyBvZiBtYXRjaGVkIGNlbGwKbXV0YW50cy5zY2UkaW5kZXhQQzEgPC0gY2RzY2UkbGFiZWwuVU1BUF8xCm11dGFudHMuc2NlJGluZGV4UEMyIDwtIGNkc2NlJGxhYmVsLlVNQVBfMgojbXV0YW50cy5zY2UkcGJwdCA8LSBjZHNjZSRwc2V1ZG90aW1lCiNtdXRhbnRzLnNjZSRwYmJ1bGsgPC0gY2RzY2UkYnVsawptdXRhbnRzLnNjZSR0b3BjZWxsX3NwIDwtIG11dGFudHMuc2NlJHRvcGNlbGxfYWMKbXV0YW50cy5zY2UkdG9wc2ltIDwtIHRvcHNpbQptdXRhbnRzLnNjZSR0b3BjZWxsX3NwW211dGFudHMuc2NlJHRvcHNpbSA8IDAuNF0gPC0gInVuYXNzaWduZWQiCnRhYmxlKG11dGFudHMuc2NlJHRvcGNlbGxfc3ApCmBgYAoKYGBge3J9CiMjIHNlZSBob3cgdGhpcyBvdmVybGFwcyB3aXRoIGZsdW9yZXNjZW5jZSBzb3J0ZWQgb24gZm9yIDgyMCB0byBjb25maXJtIGFjY3VyYWN5CmRmXzgyMCA8LSBjb2xEYXRhKG11dGFudHMuc2NlKVtjb2xEYXRhKG11dGFudHMuc2NlKSRsYWJlbC5nZW5ldGljX2JhY2tncm91bmQgPT0iUEJBTktBXzgyMCIsIF0KdGFibGUoZGZfODIwJHRvcGNlbGxfc3AsIGRmXzgyMCRsYWJlbC5mbHVvcmVzZW5jZV9zb3J0ZWRfb24pCmBgYAoKYGBge3J9CnRhYmxlKGNvbERhdGEobXV0YW50cy5zY2UpJHRvcGNlbGxfc3AsIGNvbERhdGEobXV0YW50cy5zY2UpJGxhYmVsLmlkZW50aXR5X25hbWVfdXBkYXRlZCkKYGBgCgoKYGBge3J9CiMjIyMgVE9QIDNOTiBtZXRob2QKCiNUaGlzIGZ1bmN0aW9uIG1ha2VzIGEgbGlzdCBvZiB0aGUgUEMgbWVhbnMgZm9yIGVhY2ggY2VsbCBhbmQgdGhlbiBkby5jYWxsIGJlbG93IHJiaW5kcyB0aGVtIGludG8gYSBkYXRhZnJhbWUgY2FsbGVkIGJpZ19kYXRhCgpkYXRhbGlzdCA9IGxpc3QoKQoKZm9yIChpIGluIGNvbG5hbWVzKHNjbWFwQ2VsbF9yZXN1bHRzJHd0JGNlbGxzKSkgewogIAogIGdldGNlbGxzdGVzdCA8LSBzY21hcENlbGxfcmVzdWx0cyR3dCRjZWxsc1sxOjMsIGldCiAgY2RzY2V0ZXN0IDwtIGNvbERhdGEoc2NlKVtnZXRjZWxsc3Rlc3QsIF0KICBQQzFtZWFuIDwtIG1lYW4oY2RzY2V0ZXN0JGxhYmVsLlVNQVBfMSkKICBQQzJtZWFuIDwtIG1lYW4oY2RzY2V0ZXN0JGxhYmVsLlVNQVBfMikKICAjIC4uLiBtYWtlIHNvbWUgZGF0YQogIGRhdCA8LSBkYXRhLmZyYW1lKGksIFBDMW1lYW4sIFBDMm1lYW4pCiAgZGF0JGkgPC0gaSAgIyBtYXliZSB5b3Ugd2FudCB0byBrZWVwIHRyYWNrIG9mIHdoaWNoIGl0ZXJhdGlvbiBwcm9kdWNlZCBpdD8KICBkYXRhbGlzdFtbaV1dIDwtIGRhdCAjIGFkZCBpdCB0byB5b3VyIGxpc3QKfQoKYmlnX2RhdGEgPSBkby5jYWxsKHJiaW5kLCBkYXRhbGlzdCkKIyBvciBiaWdfZGF0YSA8LSBkcGx5cjo6YmluZF9yb3dzKGRhdGFsaXN0KQojIG9yIGJpZ19kYXRhIDwtIGRhdGEudGFibGU6OnJiaW5kbGlzdChkYXRhbGlzdCkKCnRlc3QgPC0gYmlnX2RhdGFbMSwgXQoKZGYgPC0gZGF0YS5mcmFtZShYPWNvbERhdGEoc2NlKSRsYWJlbC5VTUFQXzEsIFk9Y29sRGF0YShzY2UpJGxhYmVsLlVNQVBfMiwgcm93Lm5hbWVzID0gcm93bmFtZXMoY29sRGF0YShzY2UpKSkKCiN0aGUgc25hcCBmdW5jdGlvbiBzbmFwcyB0byB0aGUgbmVhcmVzdCBjZWxsIGluIFBDIGNvb3JkaWFudGVzCnNuYXAgPC0gZnVuY3Rpb24oZGYsIHRlc3QpewogIHJlcXVpcmUoQmlvYmFzZSkKICBkIDwtIG1hdGNocHQoYXMubWF0cml4KGRmKSwKICAgICAgICAgICAgICAgYXMubWF0cml4KGRhdGEuZnJhbWUoWD10ZXN0JFBDMW1lYW4sWT10ZXN0JFBDMm1lYW4pKSkKICAKICBtaW5fcm93IDwtIHJvd25hbWVzKGRbZCRkaXN0YW5jZT09bWluKGQkZGlzdGFuY2UpLF0pCiAgCiAgdGVzdCRYX3NuYXAgPC0gdW5pcXVlKGRmW21pbl9yb3csIlgiXSkKICB0ZXN0JFlfc25hcCA8LSB1bmlxdWUoZGZbbWluX3JvdywiWSJdKQogIHRlc3QkcGJfY2VsbCA8LSBtaW5fcm93CiAgCiAgdGVzdAp9CgojdGhpcyBsb29wcyB0aHJvdWdoIGVhY2ggY2VsbCBhbmQgaW4gYmlnX2RhdGEgYW5kIHJ1bnMgdGhlIHNuYXAgZnVuY3Rpb24KZGF0YWxpc3QyID0gbGlzdCgpCmNvbG5hbWVzKGJpZ19kYXRhKSA8LSBjKCJzYW1wbGVfaWQiLCAiUEMxbWVhbiIsICJQQzJtZWFuIikKZm9yIChpIGluIHJvd25hbWVzKGJpZ19kYXRhKSkgewogIHRlc3QgPC0gYmlnX2RhdGFbaSwgXQogIGNvb3JkIDwtIHNuYXAoZGYsIHRlc3QpCiAgY29vcmQkaSA8LSBpCiAgZGF0YWxpc3QyW1tpXV0gPC0gY29vcmQKfQpiaWdfZGF0YTIgPSBkby5jYWxsKHJiaW5kLCBkYXRhbGlzdDIpCgoKdGFibGUocm93bmFtZXMoYmlnX2RhdGEyKT09cm93bmFtZXMoY29sRGF0YShtdXRhbnRzLnNjZSkpKQoKYWxscGJjZCA8LSBjb2xEYXRhKHNjZSkKYWxscGJjZCA8LSBhcy5kYXRhLmZyYW1lKGFsbHBiY2QpCnBiYWJzY2x1c3QgPC0gYWxscGJjZFssIGMoImxhYmVsLnB0X2lkX2NvbHMiLCAibGFiZWwuaWRlbnRpdHlfbmFtZV91cGRhdGVkIiwgImxhYmVsLm1vbm9jbGVfc2V4IiksIGRyb3A9RkFMU0VdCnBiYWJzY2x1c3QkcGJfc2FtcGxlX2lkIDwtIHJvd25hbWVzKHBiYWJzY2x1c3QpCgojIE5vdyBtZXJnZSB0aGUgcGMgY2VsbCBhc2lnbm1lbnRzIHdpdGggdGhlaXIgYWJzIGNsdXN0IGFuZCBnZXQgaW4gdGhlIHJpZ2h0IG9yZGVyCmJpZ19kYXRhMyA8LSBtZXJnZShiaWdfZGF0YTIsIHBiYWJzY2x1c3QsIGJ5LnggPSAicGJfY2VsbCIsIGJ5LnkgPSAicGJfc2FtcGxlX2lkIiwgYWxsLng9VFJVRSwgYWxsLnk9RkFMU0UpCmJpZ19kYXRhNCA8LSBiaWdfZGF0YTNbbWF0Y2gocm93bmFtZXMoYmlnX2RhdGEyKSwgYmlnX2RhdGEzJHNhbXBsZV9pZCksIF0KCgpjb2xvcnMgPC0gYygiNiI9IiM3OEM2NzkiLAogICAgICAgICAgICAiMiI9IiNEMUVDOUYiLAogICAgICAgICAgICAiMCI9IiNGRUIyNEMiLAogICAgICAgICAgICAiMSI9IiNGNENGNjMiLAogICAgICAgICAgICAiMyI9IiNGRUVFQUEiLAogICAgICAgICAgICAiNCI9IiM4NUIxRDMiLAogICAgICAgICAgICAiNyI9IiM5ZWNhZTEiLAogICAgICAgICAgICAiNSI9IiNDOUU4RjEiLAogICAgICAgICAgICAiTSI9ICIjQjdCN0Q4IiwKICAgICAgICAgICAgIkYiPSIjOUM5NkM2IiwKICAgICAgICAgICAgInVuYXNzaWduZWQiPSJibGFjayIpCgpnZ3Bsb3QoYmlnX2RhdGE0LCBhZXMoUEMxbWVhbiwgUEMybWVhbikpICsKICBnZW9tX3BvaW50KGNvbCA9IGJpZ19kYXRhNCRsYWJlbC5wdF9pZF9jb2xzKSArCiAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArCiAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkKCiMrIGdlb21fcG9pbnQoYWVzKGNvbG91cj1mYWN0b3IoYmlnX2RhdGE0JGxhYmVsLmxhYmVsLnB0X2lkX2NvbHMpKSkgKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3JzKSAKCiAgICAgICAgICAgICAgICAgICAgIAoKZ2dwbG90KGJpZ19kYXRhNCwgYWVzKFhfc25hcCwgWV9zbmFwKSkgKwogIGdlb21fcG9pbnQoY29sID0gYmlnX2RhdGE0JGxhYmVsLnB0X2lkX2NvbHMpICsKICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsKICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSAKCiMrIGdlb21fcG9pbnQoYWVzKGNvbG91cj1mYWN0b3IoYmlnX2RhdGE0JGxhYmVsLmxhYmVsLnB0X2lkX2NvbHMpKSkgKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3JzKSAKCiMjYWRkIGluZm8gdG8gU0NFIGFuZCBzYXZlIGNvbERhdGEsIHRvIGJlIGFuIGFzc2lnbmVkIGNlbGwgYWxsIDNOTiBtdXN0IGhhdmUgYSBjb3Mgc2ltID4wLjQKc2NtYXBDZWxsX3Jlc3VsdHMkd3Qkc2ltaWxhcml0aWVzWywgMTozXQp0b3BzaW0xIDwtIHNjbWFwQ2VsbF9yZXN1bHRzJHd0JHNpbWlsYXJpdGllc1sxLCBdCnRvcHNpbTIgPC0gc2NtYXBDZWxsX3Jlc3VsdHMkd3Qkc2ltaWxhcml0aWVzWzIsIF0KdG9wc2ltMyA8LSBzY21hcENlbGxfcmVzdWx0cyR3dCRzaW1pbGFyaXRpZXNbMywgXQoKdGFibGUoYmlnX2RhdGE0JHNhbXBsZV9pZD09cm93bmFtZXMoY29sRGF0YShtdXRhbnRzLnNjZSkpKQojcGZvYmokcGJfY2VsbCA8LSBiaWdfZGF0YTQkcGJfY2VsbAojcGZvYmokUEMxbWVhbiA8LSBiaWdfZGF0YTQkUEMxbWVhbgpiZDQgPC0gYmlnX2RhdGE0WywgYygicGJfY2VsbCIsICJzYW1wbGVfaWQiLCAiUEMxbWVhbiIsICJQQzJtZWFuIiwgIlhfc25hcCIsICJZX3NuYXAiLCAibGFiZWwucHRfaWRfY29scyIsICJsYWJlbC5pZGVudGl0eV9uYW1lX3VwZGF0ZWQiLCAibGFiZWwubW9ub2NsZV9zZXgiKV0KCmNvbERhdGEobXV0YW50cy5zY2UpIDwtIGNiaW5kKGNvbERhdGEobXV0YW50cy5zY2UpLCBiZDQpCgptdXRhbnRzLnNjZSR0b3BzaW0xIDwtIHRvcHNpbTEKbXV0YW50cy5zY2UkdG9wc2ltMiA8LSB0b3BzaW0yCm11dGFudHMuc2NlJHRvcHNpbTMgPC0gdG9wc2ltMwptdXRhbnRzLnNjZSRzdGFnZV9wcmVkIDwtIGJpZ19kYXRhNCRsYWJlbC5tb25vY2xlX3NleAptdXRhbnRzLnNjZSRzdGFnZV9wcmVkW211dGFudHMuc2NlJHRvcHNpbTEgPCAwLjQgfCBtdXRhbnRzLnNjZSR0b3BzaW0yIDwgMC40IHwgbXV0YW50cy5zY2UkdG9wc2ltMyA8IDAuNF0gPC0gInVuYXNzaWduZWQiCnRhYmxlKG11dGFudHMuc2NlJHN0YWdlX3ByZWQpCgojd3JpdGUuY3N2KGJkNCwgInBmY2VsbGFzc2lnbm1lbnRzd2l0aG1lYW4zbm5fMjAxODEwMjkuY3N2IikKI3dyaXRlLmNzdihjb2xEYXRhKHBmb2JqKSwgInBmM2Q3MTAwc2NtYXBjbHVzdHMybWV0aG9kaW5kZXhuMTAwXzIwMTkwMTA3LmNzdiIpCmBgYAoKYGBge3J9CiMjIHNlZSBob3cgdGhpcyBvdmVybGFwcyB3aXRoIGZsdW9yZXNjZW5jZSBzb3J0ZWQgb24gZm9yIDgyMCB0byBjb25maXJtIGFjY3VyYWN5CmRmXzgyMCA8LSBjb2xEYXRhKG11dGFudHMuc2NlKVtjb2xEYXRhKG11dGFudHMuc2NlKSRsYWJlbC5nZW5ldGljX2JhY2tncm91bmQgPT0iUEJBTktBXzgyMCIsIF0KdGFibGUoZGZfODIwJHN0YWdlX3ByZWQsIGRmXzgyMCRsYWJlbC5mbHVvcmVzZW5jZV9zb3J0ZWRfb24pCmBgYAoKYGBge3J9CnRhYmxlKGNvbERhdGEobXV0YW50cy5zY2UpJHN0YWdlX3ByZWQsIGNvbERhdGEobXV0YW50cy5zY2UpJGxhYmVsLmlkZW50aXR5X25hbWVfdXBkYXRlZCkKYGBgCgoKIyMgbWFrZSBmaW5hbCBwbG90IHdpdGggTUNBIGRhdGEgYmVsb3cKYGBge3J9CiMjIFJlYWQgaW4gTUNBIGRhdGEKcGhlbm8gPC0gcmVhZC5jc3YoIi4uL3NjbWFwL2FsbHBiMTB4X3BoZW5vLmNzdiIpCiMjIGV4dHJhY3Qgcm93cyBuZWVkZWQgZm9yIHBsb3R0aW5nCmRmX3Bsb3QgPC0gcGhlbm9bLGMoIlBDMl8zZCIsICJQQzNfM2QiLCAiYWJzY2x1c3QzIildCmRmX3Bsb3QkZXhwZXJpbWVudCA8LSBkZl9wbG90JGFic2NsdXN0MwoKIyMgZXh0cmFjdCByb3dzIG5lZWRlZCBmb3IgcGxvdHRpbmcgZnJvbSBtYXBwZWQgb2JqZWN0CmRmX3Bsb3RfcG0gPC0gYXMuZGF0YS5mcmFtZShjb2xEYXRhKHBtX3NzMl9maWVsZC5zY2Uub3J0aCkpCmRmX3Bsb3RfcG0gPC0gZGZfcGxvdF9wbVsgLGMoIlhfc25hcCIsICJZX3NuYXAiLCAibGFiZWwuYWJzY2x1c3QzIildCmRmX3Bsb3RfcG0kZXhwZXJpbWVudCA8LSAicG0iCmNvbG5hbWVzKGRmX3Bsb3RfcG0pIDwtIGMoIlBDMl8zZCIsICJQQzNfM2QiLCAiYWJzY2x1c3QzIiwgImV4cGVyaW1lbnQiKQoKIyMgZXh0cmFjdCByb3dzIG5lZWRlZCBmb3IgcGxvdHRpbmcgZnJvbSBtYXBwZWQgb2JqZWN0CmRmX3Bsb3RfcGYgPC0gYXMuZGF0YS5mcmFtZShjb2xEYXRhKHBmX3NzMl9maWVsZC5zY2Uub3J0aCkpCmRmX3Bsb3RfcGYgPC0gZGZfcGxvdF9wZlsgLGMoIlhfc25hcCIsICJZX3NuYXAiLCAibGFiZWwuYWJzY2x1c3QzIildCmRmX3Bsb3RfcGYkZXhwZXJpbWVudCA8LSAicGYiCmNvbG5hbWVzKGRmX3Bsb3RfcGYpIDwtIGMoIlBDMl8zZCIsICJQQzNfM2QiLCAiYWJzY2x1c3QzIiwgImV4cGVyaW1lbnQiKQoKIyMgYmluZCB0b2dldGhlcgpkZl9wbG90IDwtIHJiaW5kKGRmX3Bsb3QsIGRmX3Bsb3RfcGYsIGRmX3Bsb3RfcG0pCgpjb2xvcnMgPC0gYygiNiI9IiM3OEM2NzkiLAogICAgICAgICAgICAiMiI9IiNEMUVDOUYiLAogICAgICAgICAgICAiMCI9IiNGRUIyNEMiLAogICAgICAgICAgICAiMSI9IiNGNENGNjMiLAogICAgICAgICAgICAiMyI9IiNGRUVFQUEiLAogICAgICAgICAgICAiNCI9IiM4NUIxRDMiLAogICAgICAgICAgICAiNyI9IiM5ZWNhZTEiLAogICAgICAgICAgICAiNSI9IiNDOUU4RjEiLAogICAgICAgICAgICAiTSI9ICIjQjdCN0Q4IiwKICAgICAgICAgICAgIkYiPSIjOUM5NkM2IiwKICAgICAgICAgICAgInVuYXNzaWduZWQiPSJibGFjayIsCiAgICAgICAgICAgICJwbSIgPSAiI2RjNjVhNCIsCiAgICAgICAgICAgICJwZiIgPSAiIzI0MjQ1ZiIpCgojIyBhZGQgYWxwaGEgZm9yIHBsb3R0aW5nCmRmX3Bsb3QkYWxwaGFbIWRmX3Bsb3QkZXhwZXJpbWVudCA9PSAicG0iXSA8LSAwLjUKZGZfcGxvdCRhbHBoYVtkZl9wbG90JGV4cGVyaW1lbnQgPT0gInBtIl0gPC0gMQpkZl9wbG90JGFscGhhW2RmX3Bsb3QkZXhwZXJpbWVudCA9PSAicGYiXSA8LSAxCgojI3Bsb3QKc2NtYXBfcGNhIDwtIGdncGxvdChkZl9wbG90LCBhZXMoeD1QQzJfM2QsIHkgPSBQQzNfM2QsY29sb3VyPWV4cGVyaW1lbnQsIGFscGhhID0gYWxwaGEpKSArIAogIGdlb21fcG9pbnQoKSArCiAgdGhlbWVfdm9pZCgpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3JzKSArCiAgIyMgcmVtb3ZlIGFscGhhIHNjYWxlCiAgc2NhbGVfYWxwaGFfY29udGludW91cyhndWlkZT1GQUxTRSkKICAjIyBkcmF3IHJpbmcgYXJvdW5kIGZpZWxkIHNhbXBsZXMKICAjZ2VvbV9wb2ludChkYXRhPWRmX3Bsb3RbZGZfcGxvdCRleHBlcmltZW50ID09ICJwbSIsIF0sIHBjaD0yMSwgZmlsbD1OQSwgc2l6ZT0yLCBjb2xvdXI9ImJsYWNrIiwgc3Ryb2tlPTEpICsKICAjIyBtYWtlIG5vbi1maWVsZCBzYW1wbGVzIG1vcmUgb3BhcXVlCiAgI2dlb21fcG9pbnQoZGF0YT1kZl9wbG90Wy1kZl9wbG90JGV4cGVyaW1lbnQgPT0gInBtIiwgXSwgYWxwaGEgPSAwLjIpCgojIyB2aWV3CnNjbWFwX3BjYV8yIDwtIHNjbWFwX3BjYSArIAogIGd1aWRlcyhjb2xvdXI9Z3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZT00KSkpCgpzY21hcF9wY2FfMgpgYGAKCnNhdmUKYGBge3J9CiNnZ3NhdmUoIi4uL2ltYWdlc190b19leHBvcnQvZmllbGRfc2FtcGxlc19zY21hcC5wbmciLCBwbG90ID0gc2NtYXBfcGNhXzIsIGRldmljZSA9ICJwbmciLCBwYXRoID0gTlVMTCwgc2NhbGUgPSAxLCB3aWR0aCA9IDE1LCBoZWlnaHQgPSAxMCwgdW5pdHMgPSAiY20iLCBkcGkgPSAzMDAsIGxpbWl0c2l6ZSA9IFRSVUUpCmBgYAoKIyMgT3ZlcmxhcCBhbmQgdmFsaWRhdGlvbgoKYGBge3J9CgpgYGAKCmBgYHtyfQoKYGBgCgojIDExLiBTYXZlIGFuZCBFeHBvcnQgey50YWJzZXR9CgojIyBzYXZlCgpTYXZlIGVudmlyb25tZW50CmBgYHtyfQojIyBUaGlzIHNhdmVzIGV2ZXJ5dGhpbmcgaW4gdGhlIGdsb2JhbCBlbnZpcm9ubWVudCBmb3IgZWFzeSByZWNhbGwgbGF0ZXIKI3NhdmUuaW1hZ2UoZmlsZSA9ICJHQ1NLT19tZXJnZS5SRGF0YSIpCiNsb2FkKGZpbGUgPSAiR0NTS09fbWVyZ2UuUkRhdGEiKQpgYGAKClNhdmUgb2JqZWN0KHMpCmBgYHtyfQojIyBTYXZlIGFuIG9iamVjdCB0byBhIGZpbGUKc2F2ZVJEUyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleCwgZmlsZSA9ICIuLi9kYXRhX3RvX2V4cG9ydC90ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleC5SRFMiKQojIyBSZXN0b3JlIHRoZSBvYmplY3QKI3JlYWRSRFMoZmlsZSA9ICIuLi9kYXRhX3RvX2V4cG9ydC90ZW54Lm11dGFudC5pbnRlZ3JhdGVkLnNleC5SRFMiKQoKIyMgc2F2ZSBpbnRlZ3JhdGVkIG9iamVjdCB0byBmaWxlCnNhdmVSRFModGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmlsZSA9ICIuLi9kYXRhX3RvX2V4cG9ydC90ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLlJEUyIpIAojIyByZXN0b3JlIHRoZSBvYmplY3QKI3RlbnguanVzdHd0LmludGVncmF0ZWQgPC0gcmVhZFJEUygiLi4vZGF0YV90b19leHBvcnQvdGVueC5qdXN0d3QuaW50ZWdyYXRlZC5SRFMiKQoKIyMgc2F2ZSBtb25vY2xlIG9iamVjdApzYXZlUkRTKG1vbm9jbGUub2JqZWN0LmFsbCwgZmlsZSA9ICIuLi9kYXRhX3RvX2V4cG9ydC9tb25vY2xlLm9iamVjdC5hbGwuUkRTIikgCiMjIHJlc3RvcmUgdGhlIG9iamVjdAojbW9ub2NsZS5vYmplY3QuYWxsIDwtIHJlYWRSRFMoIi4uL2RhdGFfdG9fZXhwb3J0L21vbm9jbGUub2JqZWN0LmFsbC5SRFMiKQoKIyMgc2F2ZSBpbnRlZ3JhdGVkIG9iamVjdCB0byBmaWxlCiNzYXZlUkRTKEdDU0tPX211dGFudHMsIGZpbGUgPSAiLi4vZGF0YV90b19leHBvcnQvR0NTS09fbXV0YW50cy5SRFMiKSAKIyMgcmVzdG9yZSB0aGUgb2JqZWN0CiN0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIHJlYWRSRFMoIi4uL2RhdGFfdG9fZXhwb3J0L3RlbnguanVzdHd0LmludGVncmF0ZWQuUkRTIikKCiMjIGV4dHJhY3QgVU1BUCBjb29yZGluYXRlcyBhbmQgbWV0YWRhdGEKIyMgZXh0cmFjdCBtZXRhZGF0YQptY2Ffd2Vic2l0ZV9kZiA8LSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YQoKIyMgYWRkIHVtYXAgLSBtZXJnZSBvbiByb3cgbmFtZXMgYW5kIHRoZW4gbWFrZSBzdXJlIHJvdyBuYW1lcyBhcmUgbm90IGRyb3BwZWQgb3IgYWRkZWQKbWNhX3dlYnNpdGVfZGYgPC0gdHJhbnNmb3JtKG1lcmdlKG1jYV93ZWJzaXRlX2RmLCB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQHJlZHVjdGlvbnNbWyJ1bWFwIl1dQGNlbGwuZW1iZWRkaW5ncywgYnk9MCwgYWxsPVRSVUUpLCByb3cubmFtZXM9Um93Lm5hbWVzLCBSb3cubmFtZXM9TlVMTCkKCiMjIHNlbmQgdGhpcyB0byBzdW5pbDoKIyBnZ3Bsb3QobWNhX3dlYnNpdGVfZGYsIGFlcyh4ID0gVU1BUF8xLCB5ID0gVU1BUF8yKSkgKwojIGdlb21fcG9pbnQoY29sID0gbWNhX3dlYnNpdGVfZGYkcHRfaWRfY29scykgKwojIHRoZW1lX3ZvaWQoKSArCiMgY29vcmRfZml4ZWQoKQoKIyMgZXhwb3J0CndyaXRlLmNzdihtY2Ffd2Vic2l0ZV9kZiwgZmlsZSA9ICIuLi9kYXRhX3RvX2V4cG9ydC9tY2Ffd2Vic2l0ZV9kZi5jc3YiKQpgYGAKCkNsZWFuIHVwCmBgYHtyfQojcm0oc3MyX3d0X2NlbGxzKQojcm0odGVueC5qdXN0d3QuaW50ZWdyYXRlZCkKI3JtKHRlbnguanVzdHd0Lmxpc3QpCmBgYAoKIyMgZmluYWwgZmlndXJlIGNvbnN0cnVjdGlvbgoKW0Nvd3Bsb3RdKGh0dHBzOi8vd2lsa2VsYWIub3JnL2Nvd3Bsb3QvYXJ0aWNsZXMvcGxvdF9ncmlkLmh0bWwpKHBsb3RfZ3JpZCksIFtwYXRjaHdvcmtdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9wYXRjaHdvcmsvdmlnbmV0dGVzL3BhdGNod29yay5odG1sKSh3cmFwX3Bsb3RzKSwgYW5kIFtnZ3B1YnJdKGh0dHA6Ly93d3cuc3RoZGEuY29tL2VuZ2xpc2gvYXJ0aWNsZXMvMjQtZ2dwdWJyLXB1YmxpY2F0aW9uLXJlYWR5LXBsb3RzLzgxLWdncGxvdDItZWFzeS13YXktdG8tbWl4LW11bHRpcGxlLWdyYXBocy1vbi10aGUtc2FtZS1wYWdlLykgY2FuIGFsbCBhbGxvdyBtdWx0aXBsZSBwbG90cyB0byBiZSBwbG90dGVkIHRvZ2V0aGVyLiAKCmBgYHtyLCBmaWcuaGVpZ2h0ID0gMTEuNywgZmlnLndpZHRoID0gOC4zfQojIyBBCiMgdW1hcF9pZF9wdAojIyBCCiMgbWFya2VyIGdlbmUgZXhwcmVzc2lvbgojIyBDCiMgTXV0YW50IGdlbmUgZXhwcmVzc2lvbgojIyBECiMgTW9kdWxlcwoKI0ZpZ3VyZV9BIDwtIGdyaWQuYXJyYW5nZShhcnJhbmdlR3JvYihRQ19jb21wb3NpdGVfcGxvdCwgUUNfbWl0b192aW9saW4sIFFDX21pdG9fZ3JhcGgsIFFDX2J5X2dlbm90eXBlLCBtYXBwaW5nX3JhdGVfcGxvdCksIG5yb3c9MyksIG5yb3c9MiwgaGVpZ2h0cz1jKDEwLDIpKQoKIyMgY293cGxvdCBtZXRob2QKIyMgY2FuIHVzZSB0aGlzIGZvciBsYWJlbHM6IHRvdXBwZXIobGV0dGVycylbMToxMF0KCiMjIEMuIE11dGFudCBnZW5lcwptdXRhbnRfZ2VuZXNfZmlndXJlIDwtIHBsb3RfZ3JpZCgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyMgbWFya2VyIGdlbmVzIHN0YXJ0cwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X0ZBTUIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfTVNQOCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9NU1AxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X0FQMkcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfQ0NQMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9NRzEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMjIG11dGFudCBnZW5lcyBzdGFydHMgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X2dkMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9tZDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfbWQyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X21kMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9tZDQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X21kNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9mZDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfZmQyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X2ZkMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9mZDQsIAogIGxhYmVsX3NpemUgPSAxLCAKICBucm93ID0gNCkKCiMjIGxhYmVscyBhcyB1cHBlcmNhc2UgbGV0dGVyczoKI2ModG91cHBlcihsZXR0ZXJzKVsyOjE3XSkKIyBsYWJlbHMgYXMgcm9tYW4gbnVtZXJhbHM6CiMgYyh0b2xvd2VyKGFzLnJvbWFuKGMoMjoxNykpCgpGaWd1cmVfcHVibGljYXRpb24gPC0gcGxvdF9ncmlkKHVtYXBfaWRfcHQgKyB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhbnRfZ2VuZXNfZmlndXJlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBlbXB0eSBwbG90IHRvIGdpdmUgc3BhY2luZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdncGxvdCgpICsgdGhlbWVfdm9pZCgpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoJ0EnLCAnQicpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbF9zaXplID0gMTIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBucm93PTIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbF9oZWlnaHRzID0gYygxLCAxLCA0KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVsX3dpZHRocyA9IGMoMSwgMiwgMykpCgpGaWd1cmVfcHVibGljYXRpb24KYGBgCgpzYXZlCmBgYHtyfQpnZ3NhdmUoIi4uL2ltYWdlc190b19leHBvcnQvRmlndXJlX0MucG5nIiwgcGxvdCA9IEZpZ3VyZV9wdWJsaWNhdGlvbiwgZGV2aWNlID0gInBuZyIsIHBhdGggPSBOVUxMLCBzY2FsZSA9IDEsIHdpZHRoID0gMjEsIGhlaWdodCA9IDI5LjcsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKCmBgYHtyLCBmaWcuaGVpZ2h0ID0gMTEuNywgZmlnLndpZHRoID0gOC4zfQpsYXlvdXQgPC0gIgpBQUFCQkIKQ0NEREVFCkZGR0dISApJSUpKS0sKIgoKRmlndXJlX3B1YmxpY2F0aW9uX0EgPC0gKGNvbXBvc2l0aW9uX3VtYXBfMTB4ICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAxMCkpKSArCihjb21wb3NpdGlvbl91bWFwX3NzMiArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMTApKSkgKyAKcGxvdF9sYXlvdXQobmNvbCA9IDIpCgpGaWd1cmVfcHVibGljYXRpb24gPC0gRmlndXJlX3B1YmxpY2F0aW9uX0EgKwojKFVNQVBfaG9vICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAxMCkpICsgbGFicyh0aXRsZT0iUHJlZGljdGVkIEFzZXh1YWwgQ3ljbGUgUmVhbCBUaW1lcG9pbnQiKSkgKwojKFVNQVBfa2FzaWEgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDEwKSkgKyBsYWJzKHRpdGxlPSJQcmVkaWN0ZWQgR2FtZXRvY3l0b2dlbmVzaXMgUmVhbCBUaW1lcG9pbnQiKSkgKwogICMjIG1hcmtlciBnZW5lcwptYXJrZXJfZ2VuZV9wbG90X0ZBTUIgKwptYXJrZXJfZ2VuZV9wbG90X01TUDggKwptYXJrZXJfZ2VuZV9wbG90X01TUDEgKwptYXJrZXJfZ2VuZV9wbG90X0NEUEs1ICsKbWFya2VyX2dlbmVfcGxvdF9BUDJHICsKbWFya2VyX2dlbmVfcGxvdF9DQ1AyICsKbWFya2VyX2dlbmVfcGxvdF9NRzEgKwptYXJrZXJfZ2VuZV9wbG90X09SQzEgKwptYXJrZXJfZ2VuZV9wbG90X01DTTQgKwogICMjIG11dGFudCBnZW5lcyBzdGFydHMgIAojbWFya2VyX2dlbmVfcGxvdF9nZDEgKwojbWFya2VyX2dlbmVfcGxvdF9tZDEgKwojbWFya2VyX2dlbmVfcGxvdF9tZDIgKwojbWFya2VyX2dlbmVfcGxvdF9tZDMgKwojbWFya2VyX2dlbmVfcGxvdF9tZDQgKyAKI21hcmtlcl9nZW5lX3Bsb3RfbWQ1ICsKI21hcmtlcl9nZW5lX3Bsb3RfZmQxICsKI21hcmtlcl9nZW5lX3Bsb3RfZmQyICsKI21hcmtlcl9nZW5lX3Bsb3RfZmQzICsKI21hcmtlcl9nZW5lX3Bsb3RfZmQ0ICsgCnBsb3RfbGF5b3V0KG5jb2wgPSA2LCAKICAgICAgICAgICAgd2lkdGhzID0gYygxLCAxLCAxLCAxLCAxICwxKSwKICAgICAgICAgICAgaGVpZ2h0cyA9IGMoMiwgMSwgMSwgMSksCiAgICAgICAgICAgIGRlc2lnbiA9IGxheW91dAogICAgICAgICAgICApCgpGaWd1cmVfcHVibGljYXRpb24KYGBgCgpzYXZlCmBgYHtyfQpnZ3NhdmUoIi4uL2ltYWdlc190b19leHBvcnQvRmlndXJlX1MyLnBuZyIsIHBsb3QgPSBGaWd1cmVfcHVibGljYXRpb24sIGRldmljZSA9ICJwbmciLCBwYXRoID0gTlVMTCwgc2NhbGUgPSAxLCB3aWR0aCA9IDIxLCBoZWlnaHQgPSAyOS43LCB1bml0cyA9ICJjbSIsIGRwaSA9IDMwMCwgbGltaXRzaXplID0gVFJVRSkKYGBgCgojIEFwcGVuZGl4IHsudGFic2V0fQoKIyMgU2Vzc2lvbiBJbmZvIApgYGB7ciwgZWNobyA9IEZBTFNFfQpzZXNzaW9uSW5mbygpCmBgYAoKIyBFeHByZXNzaW9uIHBsb3RzCgojIyMjIEV4cHJlc3Npb24gLSByYXcgLSBWaXJpZGlzCmBgYHtyLCBmaWcuaGVpZ2h0ID0gMTUsIGZpZy53aWR0aCA9IDE1fQojIyBmaW5kIGEgZ29vZCByaW5nIG1hcmtlciwgdG8gc2VlIGlmIHRoZXJlIGlzIGEgYmV0dGVyIG9uZSB0aGFuIHRoZSBvbmVzIHJlcG9ydGVkCiNtYXJrZXJzX3JpbmcgPC0gRmluZE1hcmtlcnModGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgaWRlbnQuMSA9IGMoIjQiLCAiNSIsICIxNiIsICIxMSIsICI3IiwgIjMiLCAiOSIsICIwIiwgIjIyIikpCiNoZWFkKG1hcmtlcnNfcmluZykKCiMgUEJBTktBLTEzMTk1MDAgLSBDQ1AyIC0gZmVtYWxlIC0gdXNlZCBpbiA4MjAgbGluZQojIFBCQU5LQS0wNDE2MTAwIC0gTUcxIC0gZHluZW5pbiBoZWF2eSBjaGFpbiAtIG1hbGUgLSB1c2VkIGluIDgyMCBsaW5lCiMgUEJBTktBLTE0Mzc1MDAgLSBBUDJHIC0gY29tbWl0bWVudAojIFBCQU5LQS0wODMxMDAwIC0gTVNQMSAtIGxhdGUgYXNleHVhbAojIFBCQU5LQS0xMTAyMjAwIC0gTVNQOCAtIGVhcmx5IGFzZXh1YWwgKGZyb20gQm96ZGVjaCBwYXBlcikKIyBQQkFOS0EtMDcxMTkwMCAtIEhTUDcwIC0gcHJvbW90ZXIgdXNlZCBmb3IgR0ZQIGFuZCBSRlAgZXhwcmVzc2lvbiBpbiB0aGUgbXV0YW50cwojIFBCQU5LQS0xNDAwNDAwIC0gRkFNQiAtIHJpbmcgbWFya2VyIC0gZGlzY292ZXJlZCBieSBsb29raW5nIGZvciBtYXJrZXIgZ2VuZXMgaW4gZGF0YQojIFBCQU5LQS0wNzIyNjAwIC0gRmFtLWIyIC0gcmluZyBtYXJrZXIgLSBodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3BtYy9hcnRpY2xlcy9QTUM1MTEzMDMxLyAKCgptYXJrZXJfZ2VuZV9wbG90X0NDUDIgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTEzMTk1MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoaXRhbGljKGNjcDIpLCAiKEZlbWFsZSkiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKQoKbWFya2VyX2dlbmVfcGxvdF9NRzEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTA0MTYxMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKGl0YWxpYyhtZzEpLCAiKE1hbGUpIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkKCm1hcmtlcl9nZW5lX3Bsb3RfQVAyRyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTQzNzUwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZShpdGFsaWMoYXAyZyksICIoQ29tbWl0bWVudCkiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKQoKbWFya2VyX2dlbmVfcGxvdF9NU1AxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0wODMxMDAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKGl0YWxpYyhtc3AxKSwgIihTY2hpem9udCkiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKQoKbWFya2VyX2dlbmVfcGxvdF9NU1A4IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0xMTAyMjAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKGl0YWxpYyhtc3A4KSwgIihBc2V4dWFsKSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpCgptYXJrZXJfZ2VuZV9wbG90X1NCUDEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTExMDEzMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoaXRhbGljKHNicDEpLCAiKFJpbmcpIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkKCm1hcmtlcl9nZW5lX3Bsb3RfRkFNQiA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDcyMjYwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZShpdGFsaWMoZmFtLWIyKSwgICIoUmluZykiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKQoKbWFya2VyX2dlbmVfcGxvdF9IU1A3MCA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDcxMTkwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKGl0YWxpYyhIU1A3MCksICAiKFJlcG9ydGVyKSIsIlxuIiwgIlBCQU5LQV8wNzExOTAwIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkKCiMjb3JpZ2luYWwgbGFiZWw6CiMgbGFicyh0aXRsZSA9IHBhc3RlKCIoQ0NQMjsgRmVtYWxlKSIsIlxuIiwgIlBCQU5LQV8xMzE5NTAwIikpCgojIyBwbG90CiMjIGNvd3Bsb3QgbWV0aG9kCm1hcmtlcl9nZW5lX3Bsb3RfYWxsIDwtIHBsb3RfZ3JpZChtYXJrZXJfZ2VuZV9wbG90X0ZBTUIsIG1hcmtlcl9nZW5lX3Bsb3RfTVNQOCwgbWFya2VyX2dlbmVfcGxvdF9NU1AxLCBtYXJrZXJfZ2VuZV9wbG90X0FQMkcsIG1hcmtlcl9nZW5lX3Bsb3RfQ0NQMiwgbWFya2VyX2dlbmVfcGxvdF9NRzEsIG1hcmtlcl9nZW5lX3Bsb3RfSFNQNzAsIG5yb3c9MykKCm1hcmtlcl9nZW5lX3Bsb3RfYWxsCgojIyBwYXRjaHdvcmsgbWV0aG9kCiNtYXJrZXJfZ2VuZV9wbG90X0ZBTUIgKyBtYXJrZXJfZ2VuZV9wbG90X01TUDggKyBtYXJrZXJfZ2VuZV9wbG90X01TUDEgKyBtYXJrZXJfZ2VuZV9wbG90X0FQMkcgKyBtYXJrZXJfZ2VuZV9wbG90X0NDUDIgKyBtYXJrZXJfZ2VuZV9wbG90X01HMSArIG1hcmtlcl9nZW5lX3Bsb3RfSFNQNzAKYGBgCgojIyMjIEV4cHJlc3Npb24gLSByYXcgLSBwdXJwbGUKYGBge3IsIGZpZy5oZWlnaHQgPSAxNSwgZmlnLndpZHRoID0gMTV9CgptYXJrZXJfZ2VuZV9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygiI0QzRDNEMyIsICIjMUQxNTY0IikpKDUwKQoKbWFya2VyX2dlbmVfcGxvdF9DQ1AyIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0xMzE5NTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJDQ1AyIChGZW1hbGUpIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApCgptYXJrZXJfZ2VuZV9wbG90X01HMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDQxNjEwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIk1HMSAoTWFsZSkiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkKCm1hcmtlcl9nZW5lX3Bsb3RfQVAyRyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTQzNzUwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiQVAyRyAoQ29tbWl0bWVudCkiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkKCm1hcmtlcl9nZW5lX3Bsb3RfTVNQMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDgzMTAwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiTVNQMSAoU2NoaXpvbnQpIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApCgptYXJrZXJfZ2VuZV9wbG90X01TUDggPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTExMDIyMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIk1TUDggKEFzZXh1YWwpIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApCgptYXJrZXJfZ2VuZV9wbG90X1NCUDEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTExMDEzMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIlNCUDEgKFJpbmcpIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApCgptYXJrZXJfZ2VuZV9wbG90X0ZBTUIgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTA3MjI2MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIkZhbS1iMiAoUmluZykiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkKCm1hcmtlcl9nZW5lX3Bsb3RfSFNQNzAgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTA3MTE5MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiKEhTUDcwOyBSZXBvcnRlcikiLCJcbiIsICJQQkFOS0FfMDcxMTkwMCIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKQoKIyMgcGxvdAojIyBjb3dwbG90IG1ldGhvZAptYXJrZXJfZ2VuZV9wbG90X2FsbCA8LSBwbG90X2dyaWQobWFya2VyX2dlbmVfcGxvdF9GQU1CLCBtYXJrZXJfZ2VuZV9wbG90X01TUDgsIG1hcmtlcl9nZW5lX3Bsb3RfTVNQMSwgbWFya2VyX2dlbmVfcGxvdF9BUDJHLCBtYXJrZXJfZ2VuZV9wbG90X0NDUDIsIG1hcmtlcl9nZW5lX3Bsb3RfTUcxLCBtYXJrZXJfZ2VuZV9wbG90X0hTUDcwLCBucm93PTMpCgptYXJrZXJfZ2VuZV9wbG90X2FsbApgYGAKCiMjIyMgRXhwcmVzc2lvbiAtIGRhdGEgLSBwdXJwbGUKCmBgYHtyLCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQojIFBCQU5LQS0xNDE4MTAwICAgICAgICBHQ1NLTy0xNyAgRkQzICAgCiMgUEJBTktBLTAxMDI0MDAgICAgICAgICBHQ1NLTy0yICBNRDMgCiMgUEJBTktBLTA3MTY1MDAgICAgICAgIEdDU0tPLTE5ICBNRDQgCiMgUEJBTktBLTE0MzUyMDAgICAgICAgIEdDU0tPLTIwICBGRDQgCiMgUEJBTktBLTA5MDIzMDAgICAgICAgIEdDU0tPLTEzICBGRDIKIyBQQkFOS0EtMDQxMzQwMCAgICBHQ1NLTy0xMF84MjAgIE1ENQojIFBCQU5LQS0wODI4MDAwICAgICAgICAgR0NTS08tMyAgR0QxCiMgUEJBTktBLTEzMDI3MDAgICAgICAgR0NTS08tb29tICBNRDEgCiMgUEJBTktBLTE0NDc5MDAgICAgICAgIEdDU0tPLTI5ICBNRDIKIyBQQkFOS0EtMTQ1NDgwMCAgICAgICAgR0NTS08tMjEgIEZEMQojIFBCQU5LQS0xMTQ0ODAwICAgICAgICBHQ1NLTy0yOCAgRkQ1CgoKbWFya2VyX2dlbmVfcGxvdF8xNyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0xNDE4MTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoImZkMyIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzIgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDEwMjQwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDMiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF8xOSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wNzE2NTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kNCIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzIwIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTE0MzUyMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsICBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQ0IikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMTMgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDkwMjMwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDIiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF8xMCA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wNDEzNDAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kNSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzMgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDgyODAwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJnZDEiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF9vb20gPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTMwMjcwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDEiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF8yOSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0xNDQ3OTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMiIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzIxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTE0NTQ4MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsICBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQxIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCiMjb3JpZ2luYWwgbGFiZWw6CiMgbGFicyh0aXRsZSA9IHBhc3RlKCIoQ0NQMjsgRmVtYWxlKSIsIlxuIiwgIlBCQU5LQV8xMzE5NTAwIikpCgojIyBtYWtlIGNvbXBvc2l0ZSBwbG90Cm11dGFudF9leHByZXNzaW9uX2NvbXBvc2l0ZSA8LSB3cmFwX3Bsb3RzKG1hcmtlcl9nZW5lX3Bsb3RfMTcgLCBtYXJrZXJfZ2VuZV9wbG90XzIgLCBtYXJrZXJfZ2VuZV9wbG90XzE5ICwgbWFya2VyX2dlbmVfcGxvdF8yMCAsIG1hcmtlcl9nZW5lX3Bsb3RfMTMgLCBtYXJrZXJfZ2VuZV9wbG90XzEwICwgbWFya2VyX2dlbmVfcGxvdF8zICwgbWFya2VyX2dlbmVfcGxvdF9vb20gLCBtYXJrZXJfZ2VuZV9wbG90XzI5ICwgbWFya2VyX2dlbmVfcGxvdF8yMSAsIG5jb2wgPSA0KQogICAgICAgICAgIAojIyBwcmludAptdXRhbnRfZXhwcmVzc2lvbl9jb21wb3NpdGUKYGBgCgojIERlbnNpdHkgUGxvdHMKCiMjIyMgRGVuc2l0eSAtIHB1cnBsZQoKYGBge3J9CiMgUEJBTktBLTEzMTk1MDAgLSBDQ1AyIC0gZmVtYWxlIC0gdXNlZCBpbiA4MjAgbGluZQojIFBCQU5LQS0wNDE2MTAwIC0gTUcxIC0gZHluZW5pbiBoZWF2eSBjaGFpbiAtIG1hbGUgLSB1c2VkIGluIDgyMCBsaW5lCiMgUEJBTktBLTE0Mzc1MDAgLSBBUDJHIC0gY29tbWl0bWVudAojIFBCQU5LQS0wODMxMDAwIC0gTVNQMSAtIGxhdGUgYXNleHVhbAojIFBCQU5LQS0xMTAyMjAwIC0gTVNQOCAtIGVhcmx5IGFzZXh1YWwgKGZyb20gQm96ZGVjaCBwYXBlcikKIyBQQkFOS0EtMDcxMTkwMCAtIEhTUDcwIC0gcHJvbW90ZXIgdXNlZCBmb3IgR0ZQIGFuZCBSRlAgZXhwcmVzc2lvbiBpbiB0aGUgbXV0YW50cwojIFBCQU5LQS0xNDAwNDAwIC0gRkFNQiAtIHJpbmcgbWFya2VyIC0gZGlzY292ZXJlZCBieSBsb29raW5nIGZvciBtYXJrZXIgZ2VuZXMgaW4gZGF0YQojIFBCQU5LQS0wNzIyNjAwIC0gRmFtLWIyIC0gcmluZyBtYXJrZXIgLSBodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3BtYy9hcnRpY2xlcy9QTUM1MTEzMDMxLyAKCm1hcmtlcnNfbGlzdCA8LSBjKCJQQkFOS0EtMDgyODAwMCIsICJQQkFOS0EtMTMwMjcwMCIsICJQQkFOS0EtMTQ0NzkwMCIsICJQQkFOS0EtMDEwMjQwMCIsICJQQkFOS0EtMDcxNjUwMCIsICJQQkFOS0EtMDQxMzQwMCIsICJQQkFOS0EtMTQ1NDgwMCIsICJQQkFOS0EtMDkwMjMwMCIsICJQQkFOS0EtMTQxODEwMCIsICJQQkFOS0EtMTQzNTIwMCIpCgpsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzIDwtIHBsb3RfZGVuc2l0eSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBtYXJrZXJzX2xpc3QsIGpvaW50ID0gRkFMU0UsIGNvbWJpbmUgPSBGQUxTRSwgZGltcyA9IGMoMSwyKSwgcGFsID0gInBsYXNtYSIsIG1ldGhvZCA9ICJrcyIpCgojIyBtYWtlIGNvbXBvc2l0ZSBwbG90ClVNQVBfY29tcG9zaXRlX211dGFudF9nZW5lcyA8LSB3cmFwX3Bsb3RzKGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzFdXSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gcGFzdGUoImdkMSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1syXV0gKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBwYXN0ZSgibWQxIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1szXV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDIiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbNF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgibWQzIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzVdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kNCIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s2XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDUiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbN11dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQxIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzhdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkMiIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s5XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDMiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbMTBdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkNCIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gNCkKClVNQVBfY29tcG9zaXRlX211dGFudF9nZW5lcwpgYGAKCgojIyMjIERlbnNpdHkgLXZpcmlkaXMKCmBgYHtyfQojIFBCQU5LQS0xMzE5NTAwIC0gQ0NQMiAtIGZlbWFsZSAtIHVzZWQgaW4gODIwIGxpbmUKIyBQQkFOS0EtMDQxNjEwMCAtIE1HMSAtIGR5bmVuaW4gaGVhdnkgY2hhaW4gLSBtYWxlIC0gdXNlZCBpbiA4MjAgbGluZQojIFBCQU5LQS0xNDM3NTAwIC0gQVAyRyAtIGNvbW1pdG1lbnQKIyBQQkFOS0EtMDgzMTAwMCAtIE1TUDEgLSBsYXRlIGFzZXh1YWwKIyBQQkFOS0EtMTEwMjIwMCAtIE1TUDggLSBlYXJseSBhc2V4dWFsIChmcm9tIEJvemRlY2ggcGFwZXIpCiMgUEJBTktBLTA3MTE5MDAgLSBIU1A3MCAtIHByb21vdGVyIHVzZWQgZm9yIEdGUCBhbmQgUkZQIGV4cHJlc3Npb24gaW4gdGhlIG11dGFudHMKIyBQQkFOS0EtMTQwMDQwMCAtIEZBTUIgLSByaW5nIG1hcmtlciAtIGRpc2NvdmVyZWQgYnkgbG9va2luZyBmb3IgbWFya2VyIGdlbmVzIGluIGRhdGEKIyBQQkFOS0EtMDcyMjYwMCAtIEZhbS1iMiAtIHJpbmcgbWFya2VyIC0gaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DNTExMzAzMS8gCgptYXJrZXJzX2xpc3QgPC0gYygiUEJBTktBLTA4MjgwMDAiLCAiUEJBTktBLTEzMDI3MDAiLCAiUEJBTktBLTE0NDc5MDAiLCAiUEJBTktBLTAxMDI0MDAiLCAiUEJBTktBLTA3MTY1MDAiLCAiUEJBTktBLTA0MTM0MDAiLCAiUEJBTktBLTE0NTQ4MDAiLCAiUEJBTktBLTA5MDIzMDAiLCAiUEJBTktBLTE0MTgxMDAiLCAiUEJBTktBLTE0MzUyMDAiKQoKbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lcyA8LSBwbG90X2RlbnNpdHkodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgbWFya2Vyc19saXN0LCBqb2ludCA9IEZBTFNFLCBjb21iaW5lID0gRkFMU0UsIGRpbXMgPSBjKDEsMiksIHBhbCA9ICJwbGFzbWEiLCBtZXRob2QgPSAia3MiKQoKIyMgbWFrZSBjb21wb3NpdGUgcGxvdApVTUFQX2NvbXBvc2l0ZV9tdXRhbnRfZ2VuZXMgPC0gd3JhcF9wbG90cyhsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1sxXV0gKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJnZDEiKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1syXV0gKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBwYXN0ZSgibWQxIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzNdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMiIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzRdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMyIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkgKSsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzVdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kNCIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzZdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIm1kNSIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzddXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkMSIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzhdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkMiIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzldXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkMyIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzEwXV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDQiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gNCkKClVNQVBfY29tcG9zaXRlX211dGFudF9nZW5lcwpgYGAKCiMjIyMgRGVuc2l0eSAtIHZpcmlkaXMKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMgUEJBTktBLTA4MjgwMDAgICAgICAgICBHQ1NLTy0zICBHRDEKCiMgUEJBTktBLTEzMDI3MDAgICAgICAgR0NTS08tb29tICBNRDEgCiMgUEJBTktBLTE0NDc5MDAgICAgICAgIEdDU0tPLTI5ICBNRDIKIyBQQkFOS0EtMDEwMjQwMCAgICAgICAgIEdDU0tPLTIgIE1EMyAKIyBQQkFOS0EtMDcxNjUwMCAgICAgICAgR0NTS08tMTkgIE1ENCAKIyBQQkFOS0EtMDQxMzQwMCAgICBHQ1NLTy0xMF84MjAgIE1ENQoKIyBQQkFOS0EtMTQ1NDgwMCAgICAgICAgR0NTS08tMjEgIEZEMQojIFBCQU5LQS0wOTAyMzAwICAgICAgICBHQ1NLTy0xMyAgRkQyCiMgUEJBTktBLTE0MTgxMDAgICAgICAgIEdDU0tPLTE3ICBGRDMgICAKIyBQQkFOS0EtMTQzNTIwMCAgICAgICAgR0NTS08tMjAgIEZENCAKCm1hcmtlcnNfbGlzdCA8LSBjKCJQQkFOS0EtMDgyODAwMCIsICJQQkFOS0EtMTMwMjcwMCIsICJQQkFOS0EtMTQ0NzkwMCIsICJQQkFOS0EtMDEwMjQwMCIsICJQQkFOS0EtMDcxNjUwMCIsICJQQkFOS0EtMDQxMzQwMCIsICJQQkFOS0EtMTQ1NDgwMCIsICJQQkFOS0EtMDkwMjMwMCIsICJQQkFOS0EtMTQxODEwMCIsICJQQkFOS0EtMTQzNTIwMCIpCgpsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzIDwtIHBsb3RfZGVuc2l0eSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBtYXJrZXJzX2xpc3QsIGpvaW50ID0gRkFMU0UsIGNvbWJpbmUgPSBGQUxTRSwgZGltcyA9IGMoMSwyKSwgcGFsID0gInBsYXNtYSIsIG1ldGhvZCA9ICJrcyIpCgojIyBtYWtlIGNvbXBvc2l0ZSBwbG90ClVNQVBfY29tcG9zaXRlX211dGFudF9nZW5lcyA8LSB3cmFwX3Bsb3RzKGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzFdXSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gcGFzdGUoImdkMSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzJdXSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDEiKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbM11dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgibWQyIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbNF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgibWQzIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSApKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbNV1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ0IikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbNl1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ1IikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbN11dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQxIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbOF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQyIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbOV1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQzIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbMTBdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkNCIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSA0KQoKVU1BUF9jb21wb3NpdGVfbXV0YW50X2dlbmVzCgojIyBJRiBwdXR0aW5nIGluIE1BSU4gLSBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1syXV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT05KSkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMSIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gNC4wLCB0aXRsZSA9ICIiKSkKYGBgCgpgYGB7ciwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KIyBQQkFOS0EtMDgyODAwMCAgICAgICAgIEdDU0tPLTMgIEdEMQoKIyBQQkFOS0EtMTMwMjcwMCAgICAgICBHQ1NLTy1vb20gIE1EMSAKIyBQQkFOS0EtMTQ0NzkwMCAgICAgICAgR0NTS08tMjkgIE1EMgojIFBCQU5LQS0wMTAyNDAwICAgICAgICAgR0NTS08tMiAgTUQzIAojIFBCQU5LQS0wNzE2NTAwICAgICAgICBHQ1NLTy0xOSAgTUQ0IAojIFBCQU5LQS0wNDEzNDAwICAgIEdDU0tPLTEwXzgyMCAgTUQ1CgojIFBCQU5LQS0xNDU0ODAwICAgICAgICBHQ1NLTy0yMSAgRkQxCiMgUEJBTktBLTA5MDIzMDAgICAgICAgIEdDU0tPLTEzICBGRDIKIyBQQkFOS0EtMTQxODEwMCAgICAgICAgR0NTS08tMTcgIEZEMyAgIAojIFBCQU5LQS0xNDM1MjAwICAgICAgICBHQ1NLTy0yMCAgRkQ0IAoKbWFya2Vyc19saXN0IDwtIGMoIlBCQU5LQS0wODI4MDAwIiwgIlBCQU5LQS0xMzAyNzAwIiwgIlBCQU5LQS0xNDQ3OTAwIiwgIlBCQU5LQS0wMTAyNDAwIiwgIlBCQU5LQS0wNzE2NTAwIiwgIlBCQU5LQS0wNDEzNDAwIiwgIlBCQU5LQS0xNDU0ODAwIiwgIlBCQU5LQS0wOTAyMzAwIiwgIlBCQU5LQS0xNDE4MTAwIiwgIlBCQU5LQS0xNDM1MjAwIikKCmxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXMgPC0gcGxvdF9kZW5zaXR5KHRlbnguanVzdHd0LmludGVncmF0ZWQsIG1hcmtlcnNfbGlzdCwgam9pbnQgPSBGQUxTRSwgY29tYmluZSA9IEZBTFNFLCBkaW1zID0gYygxLDIpLCBwYWwgPSAicGxhc21hIiwgbWV0aG9kID0gIndrZGUiLCBzbG90ID0gJ2RhdGEnKQoKIyMgbWFrZSBjb21wb3NpdGUgcGxvdApVTUFQX2NvbXBvc2l0ZV9tdXRhbnRfZ2VuZXMgPC0gd3JhcF9wbG90cyhsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1sxXV0gKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJnZDEiKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1syXV0gKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBwYXN0ZSgibWQxIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzNdXSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMiIpKSArIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbNF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgibWQzIikpICsgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbNV1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ0IikpICsgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbNl1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ1IikpICsgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbN11dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQxIikpICsgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbOF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQyIikpICsgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbOV1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQzIikpICsgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbMTBdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkNCIpKSArIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSA0KQoKIyMgb2xkIGNvbG91ciBzY2FsZTogc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXAgKQoKVU1BUF9jb21wb3NpdGVfbXV0YW50X2dlbmVzCmBgYAoKCgoKCg==